home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Gigarom 4
/
Mac Giga-ROM 4.0 - 1993.toast
/
FILES
/
DEV
/
I-Z
/
TMON_EVA.cpt
/
EUA.Asm
< prev
next >
Wrap
Assembly Source File
|
1985-12-24
|
162KB
|
6,962 lines
;Extended Monitor User Area (Public Domain - Not For Sale)
;
;Written by Darin Adler
;
;Based upon the original user area by Waldemar Horwat
;
;Portions of this code are Copyright (c) 1985 ICOM Simulations
;The rest of the code is Copyright (c) 1985 Darin Adler
;
;Created: August 14, 1984
;Last modified: December 1, 1985
;
;This is for use with Monitor version 2.585, Macintosh ROM version $69.
;
;This is an MDS (Consulair) assembler source file.
;It may have to be modified in order to be used with other assemblers.
;
;If you have difficulties with any portion of this code (particularly
;the "discipline"), send comments or a description of your problem to:
;
; Darin Adler
; 2765 Marl Oak Dr.
; Highland Park, IL 60035
;
;Questions, comments or orders for TMON should be directed to:
;
; ICOM Simulations
; 626 Wheeling Rd.
; Wheeling, IL 60090
; (312) 520-4440
;
;I give many thanks to Waldemar Horwat for writing TMON; to Todd Squires,
;Jay Zipnick, Craig Erickson, Terry Schulenburg for using and testing the
;early versions; to Andrew Donoho and the others from Austin who continue
;to test and make wonderful suggestions; to Steve Capps for the great idea
;(and code) for "discipline"; and to all the owners of TMON, who know a
;good thing when they see it!
;
AreaSize EQU $5500
Version EQU 652
;These are the trap files, etc. for MDS.
INCLUDE MacTraps.D
INCLUDE SysEquX.D
JHideCursor EQU $800 ;vectors for Hide and Show Cursor (from old SysEqu)
JShowCursor EQU $804
INCLUDE FSEqu.D
FSFCBLen EQU $3F6 ;length of the FCBs
INCLUDE ToolEquX.D
nextMap EQU 16 ;offset from one resource map to the next
resFileID EQU 20 ;offset to the resource file ID
INCLUDE QuickEqu.D
INCLUDE PackMacs.Txt
;The following macro is for word aligned, long word values.
MACRO LONG value =
DC {value}>>16,{value}&$FFFF
|
;The next macro is for user area relative word addresses
MACRO ADDR address =
IF '{address}'='0'
DC 0
ELSE
IF '{address}'='.0'
DC 0
ELSE
DC {address}-A
ENDIF
ENDIF
|
;The following macro is for traps into the monitor.
MACRO TRAPMon string =
TRAP #$F
TRAPMon. SET *
DC.B {string}
IF *-TRAPMon. <> 16
DC.B 0
ENDIF
.ALIGN 2
|
;The next 3 macros are for user area functions.
MACRO UAFunc name,next =
.{name}
ADDR .{next}
ADDR {name}
DC.B .{name}.1-*-1
|
MACRO UAParam name,parms =
.{name}.1
.ALIGN 2
DC.B {parms}
DC.B .{name}.2-*-1
|
MACRO UACode name =
.{name}.2
.ALIGN 2
{name}
|
;These are the equates for the extended ASCII used in names.
End.If EQU $00
If.Else EQU $01
If.Pos EQU $02
If.Neg EQU $03
Colon EQU $04
Skip EQU $04 ;+1 to +10
PrHex EQU $0E ;+1 to +8
PrASCII EQU $16 ;+1 to +8
NoOp EQU $1F
DisAsm0 EQU $80
DisAsm1 EQU $81
Recognize EQU $82
;These are some useful Monitor routines.
_Print1 EQU -8(A5)
_ExiTMON EQU -12(A5)
_Print2 EQU -20(A5)
_PutASCII EQU -24(A5)
_Put1Dig EQU -28(A5)
_Put2Dig EQU -32(A5)
_Put4Dig EQU -36(A5)
_Put6Dig EQU -40(A5)
_Put8Dig EQU -44(A5)
_NextCResFile EQU -48(A5)
_FindRes EQU -52(A5)
_Recognize EQU -56(A5)
;These are some of the monitor's variables
MonExecuting.A5 EQU $15(A5)
PC.A5 EQU $4E(A5)
D0.A5 EQU $60(A5)
A0.A5 EQU $80(A5)
SP.A5 EQU $94(A5)
N.A5 EQU $98(A5)
V.A5 EQU $9C(A5)
V.A2 EQU $9C(A2)
A5.TMON EQU *-$500 ;Monitor globals relative to the user area.
MonExecuting EQU $15+A5.TMON ;This is the monitor status byte.
UserInform EQU $207+A5.TMON
TMONStart EQU $FC ;The contents of this point to the bottom of TMON.
;#################
;## ##
;## User Area ##
;## ##
;#################
A
;This is the start of the user area. See the TMON manual for details on the first 32 bytes.
_AreaSize DC AreaSize ;The size of the user area.
_Version DC Version ;The current version number.
_FlagWord DC.B %10010000 ;Refresh and screen size. (Auto-Quit and no Vector Refresh)
_Inhibits DC.B %00000000 ;Heap, label, and screen inhibit flags.
_PortConfig DC %0000000000000010 ;Printer port, DTR handshake.
_PortRate DC %1100110000001010 ;9600 baud, 8 data bits, 2 stop, no parity.
_A000Hook ADDR A000Hook ;The A000 hook.
_PrintError ADDR PrintError ;The error location.
_FirstUAFunc ADDR .Toggle ;The first user routine.
_HeapHook ADDR HeapHook ;The heap window hook.
_InitHook ADDR InitHook ;User initialization routine.
_EnterHook ADDR EnterHook ;User enter routine.
_ExitHook ADDR ExitHook ;User exit routine.
_LabelScan ADDR LabelScan ;User label table scanning routine.
_CodeLabelScan ADDR CodeLabelScan ;User label-in-code scanning routine.
_LabelFind ADDR LabelFind ;User routine to find label in table.
_CodeLabelFind ADDR CodeLabelFind ;User routine to find label in code.
_Reserved DC 0,0,0,0,0,0,0,0 ;Reserved for future use.
nasty0 LONG 'NIL!' ;Something nasty for location 0.
val10000 LONG $10000 ;A useful constant.
updating LONG 0 ;A record of the last window that called BeginUpdate.
InitHook
TST.L D0 ;Is this the first call to InitHook?
BNE.S EveryInit
FirstInit
BSR GetTrapAddressPatch ;Patch fo fix incompatibility with HyperDrive 20
BSR AppleTalkPatch ;Patch to fix incompatibility with AppleTalk interface code.
BSR DebuggerInit ;Redefine the _Debugger trap.
BSR DebuggerPatch ;Fix up TMON's detection of the _Debugger opcode.
BSR SeeThroughPatch ;Fix up the fancy screen.
EveryInit
BSR A000OnOff ;Check if we need to wire in A000 traps.
BSR ChecksumInit ;Calculate an initial value for the checksum.
BSR FreeFormPatch ;Patch to fix a bug in Free Form sound.
BSR SaveMemTop ;Get the "real" MemTop.
BSR DisciplineInit ;Initialize the discipline code.
MOVE.L nasty0,0 ;Trash location zero.
RTS
EnterHook
BSR CursorEnter ;Play games with the cursor.
BSR RecordEnter ;Make 'Trap Record' seem continuous.
RTS
ExitHook
BSR CursorExit ;Play games with the cursor.
BSR RecordExit ;Make 'Trap Record' seem continuous.
MOVE.L nasty0,0 ;Trash location zero.
RTS
HeapHook
BSR HeapIdentify
RTS
;#################################
;## ##
;## User Area Built-In Labels ##
;## ##
;#################################
;
;This is the label table built into the user area.
;
UALabelTable
MACRO Label first,last,name =
LONG {first}
LONG {last}
Label. SET *
DC.B '{name|0:8}'
DCB.B Label.+8-*,$20
|
;To add labels to this table simply add blocks of 16 bytes
;(labels as described in the manual) between the UALabelTable
;label and the UALabelTableEnd label.
Label $8, $C,BusError
Label $C, $10,AddrErr
Label $10, $14,Illegal
Label $14, $18,ZeroDiv
Label $18, $1C,ChkError
Label $1C, $20,TrapVErr
Label $20, $24,Privileg
Label $24, $28,Trace
Label $28, $2C,Line1010
Label $2C, $30,Line1111
Label $34, $38,Coproces
Label $38, $3C,FormatEr
Label $3C, $40,Uninited
Label $60, $64,Spurious
Label $64, $68,AutoInt1
Label $68, $6C,AutoInt2
Label $6C, $70,AutoInt3
Label $70, $74,AutoInt4
Label $74, $78,AutoInt5
Label $78, $7C,AutoInt6
Label $7C, $80,AutoInt7
Label $80, $C0,TRAPtble
Label $100,$102,MonkeyLives
Label $102,$104,ScrVRes
Label $104,$106,ScrHRes
Label $106,$108,ScreenRow
Label $108,$10C,MemTop
Label $10C,$110,BufPtr
Label $110,$114,StkLowPt
Label $114,$118,HeapEnd
Label $118,$11C,TheZone
Label $11C,$120,UTableBase
Label $120,$124,MacJmp
Label $124,$128,DskRtnAdr
Label $128,$12C,PollRtnAddr
Label $12C,$12D,DskVerify
Label $12D,$12E,LoadTrap
Label $12E,$12F,MmInOK
Label $12F,$130,DiskWr11
Label $130,$134,ApplLimit
Label $134,$138,SonyVars
Label $138,$13A,PWMValue
Label $13A,$13E,PollStack
Label $13E,$142,PollProc
Label $142,$144,DskErr
Label $144,$146,SysEvtMask
Label $146,$14A,SysEvtBuf
Label $14A,$154,EventQueue
Label $154,$156,EvtBufCnt
Label $156,$15A,RndSeed
Label $15A,$15C,SysVersion
Label $15C,$15D,SEvtEnb
Label $15D,$15E,DSWndUpdate
Label $15E,$15F,FontFlag
Label $15F,$160,IntFlag
Label $160,$16A,VBLQueue
Label $16A,$16E,Ticks
Label $16E,$172,MBTicks
Label $172,$173,MBState
Label $173,$174,Tocks
Label $174,$17C,KeyMap
Label $17C,$184,KeypadMap
Label $184,$186,KeyLast
Label $186,$18A,KeyTime
Label $18A,$18E,KeyRepTime
Label $18E,$190,KeyThresh
Label $190,$192,KeyRepThresh
Label $192,$1B2,Lvl1DT
Label $1B2,$1D2,Lvl2DT
Label $1D2,$1D4,UnitNtryCnt
Label $1D4,$1D8,VIA
Label $1D8,$1DC,SCCRd
Label $1DC,$1E0,SCCWr
Label $1E0,$1E4,IWM
Label $1E4,$1F8,scratch20
Label $1F8,$1F9,SPValid
Label $1F9,$1FA,SPATalkA
Label $1FA,$1FB,SPATalkB
Label $1FB,$200,SPConfig
Label $200,$204,SPAlarm
Label $204,$206,SPFont
Label $206,$207,SPKbd
Label $207,$208,SPPrint
Label $208,$209,SPVolCtl
Label $209,$20A,SPClikCaret
Label $20A,$20B,SPMisc1
Label $20B,$20C,SPMisc2
Label $1F8,$20C,SysParam
Label $20C,$210,Time
Label $210,$212,BootDrive
Label $212,$214,JShell
Label $214,$216,SFSaveDisk
Label $216,$21A,KbdVars
Label $21A,$21E,JKybdTask
Label $21E,$21F,KbdType
Label $21F,$220,AlarmState
Label $220,$222,MemError
Label $222,$226,JFlgTrkSpd
Label $226,$22A,JDiskPrime
Label $22A,$22E,JRdAddr
Label $22E,$232,JRdData
Label $232,$236,JWrData
Label $236,$23A,JSeek
Label $23A,$23E,JSetUpPoll
Label $23E,$242,JRecal
Label $242,$246,JControl
Label $246,$24A,JWakeUp
Label $24A,$24E,JReSeek
Label $24E,$252,JMakeSpdTbl
Label $252,$256,JAdrDisk
Label $256,$25A,JSetSpeed
Label $25A,$25E,NiblTbl
Label $222,$260,DiskVars
Label $260,$261,SdVolume
Label $261,$262,Finder
Label $262,$266,SoundPtr
Label $266,$26A,SoundBase
Label $26A,$27A,SoundVBL
Label $27A,$27E,SoundDCE
Label $27E,$27F,SoundActive
Label $27F,$280,SoundLevel
Label $280,$282,CurPitch
Label $282,$28A,Switcher
Label $28A,$28E,RSDHndl
Label $28E,$290,ROM85
Label $290,$291,PortAUse
Label $291,$292,PortBUse
Label $292,$29A,ScreenVars
Label $29A,$29E,JGNEFilter
Label $29E,$2A2,Key1Trans
Label $2A2,$2A6,Key2Trans
Label $2A6,$2AA,SysZone
Label $2AA,$2AE,ApplZone
Label $2AE,$2B2,ROMBase
Label $2B2,$2B6,RAMBase
Label $2B6,$2BA,BasicGlob
Label $2BA,$2BE,DSAlertTab
Label $2BE,$2CE,ExtStsDT
Label $2CE,$2CF,SCCASts
Label $2CF,$2D0,SCCBSts
Label $2D0,$2D8,SerialVars
Label $2DC,$2E0,ABusDCE
Label $2D8,$2E0,ABusVars
Label $2E0,$2F0,FinderName
Label $2F0,$2F4,DoubleTime
Label $2F4,$2F8,CaretTime
Label $2F8,$2F9,ScrDmpEnb
Label $2F9,$2FA,ScrDmpType
Label $2FA,$2FC,TagData
Label $2FC,$300,BufTgFNum
Label $300,$302,BufTgFFlg
Label $302,$304,BufTgFBkNum
Label $304,$308,BufTgDate
Label $308,$312,DrvQHdr
Label $312,$316,PWMBuf2
Label $316,$31A,MacPgm
Label $31A,$31E,Lo3Bytes
Label $31E,$322,MinStack
Label $322,$326,DefltStack
Label $326,$328,MMDefFlags
Label $328,$32C,GZRootHnd
Label $32C,$330,GZRootPtr
Label $330,$334,GZMoveHnd
Label $334,$338,DSDrawProc
Label $338,$33C,EjectNotify
Label $33C,$340,IAZNotify
Label $340,$342,CkdDB
Label $342,$344,NxtDB
Label $344,$346,MaxDB
Label $346,$347,FlushOnly
Label $347,$348,RegRsrc
Label $348,$349,FLckUnlck
Label $349,$34A,FrcSync
Label $34A,$34C,NewMount
Label $34C,$34E,DrMstrBlk
Label $34E,$352,FCBSPtr
Label $352,$356,DefVCBPtr
Label $356,$360,VCBQHdr
Label $360,$362,FSBusy
Label $362,$366,FSQHead
Label $366,$36A,FSQTail
Label $360,$36A,FSQHdr
Label $36A,$3A2,RgSvArea
Label $3A2,$3A4,ErCode
Label $3A4,$3D6,Params
Label $3D6,$3DE,FSTemp8
Label $3DE,$3E2,FSTemp4
Label $3E2,$3E6,FSQueueHook
Label $3E6,$3EA,ExtFSHook
Label $3EA,$3EE,DskSwtchHook
Label $3EE,$3F2,ReqstVol
Label $3F2,$3F6,ToExtFS
Label $3F6,$3F8,FSFCBLen
Label $3F8,$400,DSAlertRect
Label $400,$800,DispatchTab
Label $800,$804,JHideCursor
Label $804,$808,JShowCursor
Label $808,$80C,JShieldCursor
Label $80C,$810,JScrnAddr
Label $810,$814,JScrnSize
Label $814,$818,JInitCrsr
Label $818,$81C,JSetCrsr
Label $81C,$820,JCrsrObscure
Label $820,$824,JUpdateProc
Label $824,$828,ScrnBase
Label $828,$82C,MTemp
Label $82C,$830,RawMouse
Label $830,$834,Mouse
Label $834,$83C,CrsrPin
Label $83C,$844,CrsrRect
Label $844,$888,TheCrsr
Label $888,$88C,CrsrAddr
Label $88C,$8CC,CrsrSave
Label $8CC,$8CD,CrsrVis
Label $8CD,$8CE,CrsrBusy
Label $8CE,$8CF,CrsrNew
Label $8CF,$8D0,CrsrCouple
Label $8D0,$8D2,CrsrState
Label $8D2,$8D3,CrsrObscure
Label $8D3,$8D4,CrsrScale
Label $8D6,$8DA,MouseMask
Label $8DA,$8DE,MouseOffset
Label $8DE,$8E0,JournalFlag
Label $8E0,$8E4,JSwapFont
Label $8E4,$8E8,JFontInfo
Label $8E8,$8EC,JournalRef
Label $8EC,$8EE,CrsrThresh
Label $8EE,$8F2,JCrsrTask
Label $8F2,$8F3,WWExist
Label $8F3,$8F4,QDExist
Label $8F4,$8F8,JFetch
Label $8F8,$8FC,JStash
Label $8FC,$900,JIODone
Label $900,$902,CurApRefnum
Label $902,$903,LaunchFlag
Label $904,$908,CurrentA5
Label $908,$90C,CurStack
Label $910,$930,CurApName
Label $930,$934,SaveSegHandle
Label $934,$936,CurJTOffset
Label $936,$938,CurPageOption
Label $93A,$944,LoaderPBlock
Label $900,$944,LoadVars
Label $944,$946,PrintErr
Label $946,$947,ChooserBits
Label $944,$954,PrintVars
Label $954,$960,CoreEdit
Label $960,$964,scrapSize
Label $964,$968,scrapHandle
Label $968,$96A,scrapCount
Label $96A,$96C,scrapState
Label $96C,$970,scrapName
Label $970,$980,ScrapTag
Label $960,$980,ScrapVars
Label $980,$984,RomFont0
Label $984,$986,ApFontID
Label $986,$987,GotStrike
Label $987,$988,FMDefaultSize
Label $988,$98A,CurFMFamily
Label $98A,$98C,CurFMSize
Label $98C,$98D,CurFMFace
Label $98D,$98E,CurFMNeedBits
Label $98E,$990,CurFMDevice
Label $990,$994,CurFMNumer
Label $994,$998,CurFMDenom
Label $988,$998,CurFMInput
Label $998,$99A,FOutError
Label $99A,$99E,FOutFontHandle
Label $99E,$99F,FOutBold
Label $99F,$9A0,FOutItalic
Label $9A0,$9A1,FOutULOffset
Label $9A1,$9A2,FOutULShadow
Label $9A2,$9A3,FOutULThick
Label $9A3,$9A4,FOutShadow
Label $9A4,$9A5,FOutExtra
Label $9A5,$9A6,FOutAscent
Label $9A6,$9A7,FOutDescent
Label $9A7,$9A8,FOutWidMax
Label $9A8,$9A9,FOutLeading
Label $9A9,$9AA,FOutUnused
Label $9AA,$9AE,FOutNumeer
Label $9AE,$9B2,FOutDenom
Label $998,$9B2,FOutRec
Label $9B2,$9B6,FMDotsPerInch
Label $9B6,$9CE,FMStyleTab
Label $9CE,$9D6,ToolScratch
Label $9D6,$9DA,WindowList
Label $9DA,$9DC,SaveUpdate
Label $9DC,$9DE,PaintWhite
Label $9DE,$9E2,WMgrPort
Label $9E2,$9E6,DeskPort
Label $9E6,$9EA,OldStructure
Label $9EA,$9EE,OldContent
Label $9EE,$9F2,GrayRgn
Label $9F2,$9F6,SaveVisRgn
Label $9F6,$9FA,DragHook
Label $9FA,$A02,scratch8
Label $A02,$A06,OneOne
Label $A06,$A0A,MinusOne
Label $A0E,$A1C,IconBitmap
Label $A1C,$A20,MenuList
Label $A20,$A22,MBarEnable
Label $A22,$A24,CurDeKind
Label $A24,$A26,MenuFlash
Label $A26,$A28,TheMenu
Label $A28,$A2C,SavedHandle
Label $A2C,$A30,MBarHook
Label $A30,$A34,MenuHook
Label $A34,$A3C,DragPattern
Label $A3C,$A44,DeskPattern
Label $A44,$A46,DragFlag
Label $A46,$A4A,CurDragAction
Label $A4A,$A50,FPState
Label $A50,$A54,TopMapHndl
Label $A54,$A58,SysMapHndl
Label $A58,$A5A,SysMap
Label $A5A,$A5C,CurMap
Label $A5C,$A5E,ResReadOnly
Label $A5E,$A60,ResLoad
Label $A60,$A62,ResErr
Label $A62,$A63,TaskLock
Label $A63,$A64,FScaleDisable
Label $A64,$A68,CurActivate
Label $A68,$A6C,CurDeactive
Label $A6C,$A70,DeskHook
Label $A70,$A74,TEDoText
Label $A74,$A78,TERecal
Label $A78,$A84,ApplScratch
Label $A84,$A88,GhostWindow
Label $A88,$A8C,CloseOrnHook
Label $A8C,$A90,ResumeProc
Label $A90,$A94,SaveProc
Label $A94,$A98,SaveSP
Label $A98,$A9A,ANumber
Label $A9A,$A9C,ACount
Label $A9C,$AA0,DABeeper
Label $AA0,$AB0,DAStrings
Label $AB0,$AB2,TEScrpLength
Label $AB4,$AB8,TEScrpHandle
Label $AB8,$AD8,AppPacks
Label $AD8,$AE8,SysResName
Label $AEC,$AF0,AppParmHandle
Label $AF0,$AF2,DSErrCode
Label $AF2,$AF6,ResErrProc
Label $AF6,$AFA,TEWdBreak
Label $AFA,$AFC,DlgFont
UALabelTableEnd
NumUALabels EQU (UALabelTableEnd-UALabelTable)/16
;###########################
;## ##
;## User Area functions ##
;## ##
;###########################
;
;The following is the first function in the user area.
;It is used to link between two different sets of UA functions.
;
UAFunc Toggle,BlockMove
DC.B 'Toggle screens {'
DC.B If.Pos
DC.B 'generic'
DC.B If.Else
DC.B 'heap, label and A000 trap'
DC.B End.If
DC.B ' functions}'
UAParam Toggle,%00001
DC.B 0
UACode Toggle
NOT.B (A0)
BEQ.S @1
MOVE.W #.LabelTableSet-A,.Toggle-A(A2)
RTS
@1 MOVE.W #.BlockMove-A,.Toggle-A(A2)
RTS
;The 1st user area screen starts here
UAFunc BlockMove,BlockCompare
DC.B 'Block move (src dst len)'
UAParam BlockMove,%01000
UACode BlockMove
MOVE.L D0,A0 ;Call the ROM _BlockMove routine.
MOVE.L D1,A1
MOVE.L D2,D0
_BlockMove
RTS
UAFunc BlockCompare,BlockFill
DC.B 'Block compare {'
DC.B If.Neg
DC.B Skip+9
DC.B If.Else
DC.B If.Neg
DC.B 'Match',Skip+8
DC.B If.Else
DC.B 'Mismatch at ',Skip+1,PrHex+6,'/',Skip+1,PrHex+6
DC.B End.If
DC.B End.If
DC.B '} (adr1 adr2 len)',Colon
DC.B If.Pos
DC.B PrHex+6,' ',Skip+1,PrHex+6,' ',Skip+1,PrHex+6
UAParam BlockCompare,%01001
DC $FF00
LONG -1
LONG -1
LONG -1
LONG -1
LONG -1
UACode BlockCompare
TST.B D7 ;No parameters?
BEQ.S @2 ;It's a "match"
TST.L D2 ;Is the length zero or negative?
BLE.S @2 ;YES. All zero-length areas "match".
BSR AddressCheck
MOVEM.L D0/D1/D2,10(A0) ;Save the current values.
MOVE.L D0,A1
MOVE.L D1,A2
SUBQ.L #1,D2
@1 CMPM.B (A1)+,(A2)+ ;Compare one byte.
DBNE D2,@1
BNE.S Mismatch ;A mismatch.
SUB.L val10000,D2 ;This is the compare outer loop.
BCC.S @1
@2 SCC 10(A0) ;Flag whether a comparison is going.
SCC (A0)+
ST (A0) ;The blocks match.
RTS
Mismatch
CLR.W (A0)+ ;Flag a mismatch.
SUBQ.W #1,A1 ;Pass back the address of the mismatch.
MOVE.L A1,(A0)+
BSR StoreV
SUBQ.W #1,A2
MOVE.L A2,(A0)+
@1 CMPM.B (A1)+,(A2)+ ;Now search for another match.
DBEQ D2,@1
BEQ.S @2 ;A match.
SUB.L val10000,D2 ;This is the compare outer loop.
BCC.S @1
BRA.S @3
@2 SUBQ.W #1,A1 ;Move the pointers back one byte.
SUBQ.W #1,A2
@3 ADDQ.L #1,D2
MOVE.L A1,(A0)+ ;Save the pointers and the new count for the user's
MOVE.L A2,(A0)+ ;convenience.
MOVE.L D2,(A0)
RTS
UAFunc BlockFill,Search
DC.B 'Fill (bgn end val [vLen])'
UAParam BlockFill,%11000
UACode BlockFill
LSR.B #1,D7
BCC.S @1
BSR.S Measure ;Find the size of the item.
@1 MOVEQ #%10110,D6
BSR.S MeasureCheck
MOVE.L D2,D4
SUBQ.B #2,D3
BEQ.S @2 ;Do a word fill.
BCC.S @3 ;Do a longword fill.
LSL.W #8,D4 ;Do a byte fill. Copy the byte into both the low
MOVE.B D2,D4 ;and high order bytes of the low word in D2.
MOVE.W D4,D2
@2 SWAP D2 ;Copy the word into both the low and high order
MOVE.W D4,D2 ;words in D2.
@3 SUB.L D0,D1 ;If the ending address is lower than the beginning
BLT.S @5 ;address, exit.
MOVE.L D0,A0
@4 ROL.L #8,D2 ;Shift the next byte into position, and put it into
MOVE.B D2,(A0)+ ;the destination.
DBRA D1,@4
SUB.L val10000,D1 ;This is a continuation of the loop.
BCC.S @4
@5 RTS
Measure
MOVEQ #1,D4
MOVEQ #0,D3
@1 ADDQ.W #1,D3 ;Compare the value against $100, $10000, and
ROL.L #8,D4 ;$1000000. Estimate the length based on the
CMP.L D4,D2 ;results.
BCS.S @2
CMP.W #4,D3
BCS.S @1
@2 RTS
MeasureCheck
MOVEQ #4,D4 ;D4 contains the constant 4.
CMP.L D4,D3 ;The length can't be greater than four.
BLS.S @1
MOVE.L D5,D3
@1 BTST D3,D6 ;The length has to be within the requested range.
BNE.S AddressCheck
ADDQ.B #1,D3
BRA.S @1
AddressCheck
AND.L Lo3Bytes,D0 ;Strip the high bytes from the addresses.
AND.L Lo3Bytes,D1
RTS
UAFunc Search,RegisterBuffer
DC.B 'Find {'
DC.B If.Neg
DC.B 'byte'
DC.B If.Else
DC.B 'word'
DC.B End.If
DC.B ' aligned} {'
DC.B If.Neg
DC.B Skip+4
DC.B If.Else
DC.B Skip+1,PrHex+6
DC.B End.If
DC.B '} (val [vLen [bgn [end]]])',Colon
DC.B If.Pos
DC.B Skip+1,PrHex+8,' '
DC.B If.Pos
DC.B PrHex+1,' '
DC.B If.Pos
DC.B PrHex+6,' ',Skip+1,PrHex+6
UAParam Search,%11111
DC $FFFF
LONG 0
DC $FF00
LONG 0
DC $FF00
LONG -1
LONG -1
UACode Search
TST.B D7 ;If just a RETURN was pressed, toggle between byte
BNE.S @1 ;and word aligned search.
NOT.B (A0)
RTS
@1 EXG D0,D2
EXG D1,D3
SUBQ.B #1,D7 ;If vLen wasn't given, calculate it.
BNE.S @2
BSR Measure
@2 MOVEQ #%11110,D6 ;vLen can be 1..4 for byte-aligned searches and 2
TST.B (A0)+ ;or 4 for word-aligned searches.
BNE.S @3
MOVEQ #%10100,D6
@3 BSR MeasureCheck
SUBQ.B #3,D7 ;If the ending address wasn't given, set it to the
BEQ.S @4 ;end of memory.
MOVE.L RealMemTop,D1 ;Use the "real" MemTop.
SUBQ.L #1,D1
@4 ST (A0)+ ;Assume that nothing was found.
CLR.L (A0)+ ;Clear the "found" address.
CLR.W (A0)+ ;Make everything appear.
CLR.L (A0)+ ;Prevent the value itself from being found.
MOVE.W D3,(A0)+ ;Save the search size.
MOVE.L D0,(A0)+ ;Save the beginning address.
MOVE.L D1,(A0) ;Save the ending address.
MOVE.L D2,D6 ;Save the value that is being searched, but not in
SUBQ.W #1,D3 ;memory, because it would be found there.
MOVE.W D3,D4
ASL.W #3,D4 ;Shift the high-order byte of the value into the
ROR.L D4,D2 ;least significant byte of D2.
TST.B -18(A0)
BMI.S @5
BCLR D5,D0 ;Align addresses to word boundaries for word-aligned
BSET D5,D1 ;search. D5 should be zero.
@5 MOVE.L D0,A1
SUB.L D3,D1 ;Subtract the length from the ending address.
SUB.L D0,D1 ;Get the length of the area to be searched.
BLT.S @50 ;It is less than zero.
TST.B -18(A0)
BPL.S @30
@10 CMP.B (A1)+,D2 ;Does this byte match?
@11 DBEQ D1,@10
BEQ.S @12 ;YES.
SUB.L val10000,D1 ;NO. This is a high-order loop.
BCC.S @10
@50 MOVE.L D6,-10(A0)
RTS ;Pass back failure code.
@12 MOVE.W D3,D4 ;Create private copies of the address, value, and
MOVE.L D2,D5 ;length of value.
MOVE.L A1,A3
BRA.S @21
@20 ROL.L #8,D5 ;Compare the next byte in the value.
CMP.B (A3)+,D5
BNE.S @11
@21 DBRA D4,@20 ;Were all bytes present in the value compared?
CMP.L A5,A1 ;YES. Don't report a match if it is in the
BCS.S @40 ;Monitor's variables area to prevent spurious finds.
CMP.L A2,A1
BCS.S @11
@40 MOVEQ #1,D0
BRA.S @42 ;Go report a find.
@30 ROL.L #8,D2 ;D1 contains the number of words, not bytes, for
LSR.L #1,D1 ;word-aligned search.
@31 CMP.W (A1)+,D2
@32 DBEQ D1,@31
BEQ.S @33
SUB.L val10000,D1
BCC.S @31
BRA.S @50
@33 CMP.W #1,D3
BEQ.S @34
MOVE.L D2,D5
SWAP D5
CMP.W (A1),D5
BNE.S @32
@34 CMP.L A5,A1 ;YES. Don't report a match if it is in the
BCS.S @41 ;Monitor's variables area to prevent spurious finds.
CMP.L A2,A1
BCS.S @32
@41 MOVEQ #2,D0
@42 MOVE.L A1,-(A0) ;Save the address of the match plus one.
SUBQ.W #2,A0
MOVE.L D6,-(A0) ;Save the value being searched.
SUBQ.W #2,A0
SUB.W D0,A1
MOVE.L A1,-(A0) ;Pass back the address of the match.
CLR.B -(A0) ;Indicate that the search was successful.
StoreV MOVE.L A1,V.A5 ;Store this value in the V variable.
RTS
UAFunc RegisterBuffer,Print
DC.B 'Registers {'
DC.B If.Pos
DC.B Skip+1,'PC=',PrHex+8,'} (0=save, 1=load, 2=swap)'
DC.B If.Else
DC.B '} (0=save)'
UAParam RegisterBuffer,%00011
DC $FF00
DCB.W 37,0 ;37 words for the registers
UACode RegisterBuffer
TST.W D7
BNE.S BufferFunctions
ST (A0)
RTS
BufferFunctions TST.B (A0) ;Are there stored registers?
BEQ.S @10
TST.L D0
BEQ.S @10
RTS
@10 CLR.W (A0)+
LEA PC.A5,A5 ;Get the PC.
MOVEQ #37-1,D1 ;Use 37 words.
TST.L D0 ;Get the function code.
BEQ.S @1 ;SaveRegs.
SUBQ.L #2,D0
BEQ.S @2 ;SwapRegs.
BCC.S @3 ;Exit if the number wasn't between 0 and 2.
EXG A0,A5 ;LoadRegs. Do a reverse SaveRegs.
@1 MOVE.W (A5)+,(A0)+
DBRA D1,@1
RTS
@2 MOVE.W (A5),D2 ;Exchange the register sets.
MOVE.W (A0),(A5)+
MOVE.W D2,(A0)+
DBRA D1,@2
@3 RTS
;Pick one of three routines to follow this one.
UAFunc Print,Template
DC.B 'Print {'
DC.B If.Pos
DC.B If.Pos,'dump'
DC.B If.Else,'disassembly'
DC.B End.If
DC.B If.Else
DC.B If.Pos,'file'
DC.B If.Else,'heap'
DC.B End.If
DC.B End.If
DC.B '} {error=',PrHex+4,'} ('
DC.B If.Pos,'bgn end'
DC.B If.Else
DC.B If.Pos,'file'
DC.B If.Else,'zone'
DC.B End.If
DC.B '#'
DC.B End.If
DC.B ')'
UAParam Print,%00101
DC 0
PrintError DC 0
DC 0
UACode Print
TST.W D7 ;Were any arguments supplied?
BNE.S @2 ;YES. Go to the printing section.
NOT.B 1(A0) ;NO. Go to the next state in the state machine.
BNE.S @1
NOT.B (A0)
EOR.B #%00110,-2(A0) ;Adjust the number of parameters allowed.
@1 MOVE.W (A0),4(A0)
RTS
@2 MOVE.B 1(A0),D5 ;Prepare dump vs. disassembly or file vs. heap flag.
SUBQ.W #2,D7 ;Is this a dump/disassembly print?
BCS.S @3 ;NO.
MOVE.L D0,A1 ;YES.
MOVE.L D1,A4 ;Prepare the registers and go to the print routine.
JMP _Print1
@3 MOVE.W D0,D6 ;Prepare the file number.
TST.B D5
BEQ.S @4
TST.L D0 ;If the heap number is requested instead, prepare
SEQ D6 ;that.
ASL.W #8,D6
@4 JMP _Print2 ;Go to the print routine.
UAFunc Template,StackLook
DC.B 'Template {'
DC.B If.Pos
DC.B If.Pos,'WindowRecord'
DC.B If.Else,'ControlRecord'
DC.B End.If
DC.B If.Else
DC.B If.Pos,'TERec'
DC.B If.Else,'ParamBlock'
DC.B End.If
DC.B End.If
DC.B If.Pos
DC.B ' @'
DC.B PrHex+6
DC.B End.If
DC.B '} (addr)',Colon
DC.B If.Pos
DC.B PrHex+6
DC.B If.Else
DC.B If.Pos
DC.B 'RA0'
UAParam Template,%00011
DC 0
LONG -1
FutureTemplate LONG -1
UACode Template
TST.B D7
BNE.S ChoseTemplate
TST.L 2(A0)
BPL.S CanceledTemplate
NOT.B 1(A0)
BNE.S @1
NOT.B (A0)
@1 RTS
CanceledTemplate
MOVE.W #.StackLook-A,.Template-A(A2)
MOVEQ #-1,D0
MOVE.L D0,2(A0)
MOVE.L D0,6(A0)
Template.RTS RTS
ChoseTemplate
MOVE.L A0,A5
MOVE.L D0,A0
BSR CheckA0 ;If A0 is odd or NIL then don't accept it.
BCS.S Template.RTS
MOVE.W #.Template1-A,.Template-A(A2)
MOVE.W (A5)+,D0 ;Get the signatures.
MOVE.L A0,(A5) ;Put the address in the template indicator.
MOVE.L A0,A5 ;And into a handy register.
LEA Part1,A1 ;Point the registers to the templates.
LEA Part2,A2
LEA Part3,A3
LEA Part4,A4
MOVE.W D0,(A1)+ ;Inform each piece what kind it is.
MOVE.W D0,(A2)+
MOVE.W D0,(A3)+
MOVE.W D0,(A4)+
PEA FinishTemplate
TST.W D0
BPL.S @1
TST.B D0
BMI ParamTemplate
BRA TETemplate
@1 TST.B D0
BMI ControlTemplate
WindowTemplate
LEA portBits(A5),A0
MOVE.L (A0)+,(A1)+ ;baseAddr
MOVE.W (A0)+,(A1)+ ;rowBytes
MOVE.L (A0)+,(A1)+ ;bounds
MOVE.L (A0)+,(A1)+
MOVE.L (A0)+,(A1)+ ;portRect
MOVE.L (A0)+,(A1)+
MOVE.L (A0)+,(A2)+ ;visRgn
MOVE.L (A0)+,(A2)+ ;clipRgn
LEA windowKind(A5),A0
MOVE.W (A0)+,(A2)+
TST.B (A0)+ ;visible
SNE (A2)+
TST.B (A0)+ ;hilited
SNE (A2)+
TST.B (A0)+ ;goAway
SNE (A2)+
ADDQ #1,A0 ;skip "spareFlag"
MOVE.L (A0)+,(A3)+ ;strucRgn
MOVE.L (A0)+,(A3)+ ;contRgn
MOVE.L (A0)+,(A3)+ ;updateRgn
MOVE.L (A0)+,(A3)+ ;defProc
MOVE.L (A0)+,(A3)+ ;dataHandle
MOVE.L wControlList(A5),(A4)+
MOVE.L nextWindow(A5),D2
MOVE.L D2,(A4)+
MOVE.L wRefCon(A5),(A4)+
MOVE.L wTitleHandle(A5),A0
BSR IndirectA0
BCC.S @1
MOVEQ #0,D0
MOVE.L D0,A0
@1 ST (A4)+
RTS
ControlTemplate
MOVE.L (A0)+,D2 ;nextControl
MOVE.L D2,(A1)+
MOVE.L (A0)+,(A1)+ ;owner
MOVE.L (A0)+,(A1)+ ;rect
MOVE.L (A0)+,(A1)+
TST.B (A0)+ ;visible
SNE (A1)+
MOVE.B (A0)+,(A1)+ ;hilited
MOVE.W (A0)+,(A2)+ ;value
MOVE.L (A0)+,(A2)+ ;min, max
MOVE.L (A0)+,(A2)+ ;defProc
MOVE.L (A0)+,(A2)+ ;dataHandle
MOVE.L (A0)+,(A2)+ ;actionProc
MOVE.L (A0)+,(A3)+ ;refCon
ST (A4)+
AND.L Lo3Bytes,D2
BTST #0,D2 ;Check for odd address.
BNE.S D2.NIL
TST.L D2
BEQ.S D2.NIL
EXG D2,A1
MOVE.L (A1),D2
RTS
D2.NIL MOVEQ #0,D2
RTS
TETemplate
MOVE.L (A0)+,(A1)+ ;destRect
MOVE.L (A0)+,(A1)+
MOVE.L (A0)+,(A1)+ ;viewRect
MOVE.L (A0)+,(A1)+
MOVE.W teLineHite(A5),(A1)+
MOVE.W teNLines(A5),(A1)+
LEA teSelPoint(A5),A0
MOVE.L (A0)+,(A2)+
MOVE.L (A0)+,(A2)+ ;selStart, selEnd
ADDQ #2,A0 ;skip "active"
MOVE.L (A0)+,(A2)+ ;wordBreak
MOVE.L (A0)+,(A2)+ ;clikLoop
MOVE.L (A0)+,(A3)+ ;clickTime
MOVE.W (A0)+,(A3)+ ;clickLoc
MOVE.L (A0)+,(A3)+ ;caretTime
MOVE.W (A0)+,(A3)+ ;caretState
MOVE.W (A0)+,D0 ;justification
BEQ.S @1 ;left?
CMP.W MinusOne,D0
BEQ.S @1 ;right?
CMP.W #1,D0
BNE.S @2 ;center?
MOVE.W #$FF,D0 ;center
BRA.S @1
@2 MOVE.W #$FF00,D0 ;INVALID
@1 MOVE.W D0,(A3)+
MOVE.W (A0)+,(A4)+ ;length
MOVE.L (A0)+,(A4)+ ;textH
MOVE.W teFont(A5),(A4)+
LEA teSize(A5),A0
MOVE.W (A0)+,(A4)+
MOVE.L (A0)+,(A4)+ ;port
MOVE.L (A0)+,(A4)+ ;hiHook
MOVE.L (A0)+,(A4)+ ;carHook
MOVEQ #-1,D2
MOVE.L D2,A0 ;A0 is for the name.
MOVE.L A5,D2 ;do the same one over again
CLR.B (A4)+
RTS
ParamTemplate
MOVE.L (A0)+,(A1)+ ;qLink
ADDQ #2,A0 ;skip qType
MOVE.W (A0)+,(A1)+ ;trap
MOVE.L (A0)+,(A1)+ ;cmdAddr
MOVE.L (A0)+,(A1)+ ;completion
MOVE.W (A0)+,(A1)+ ;ioResult
ADDQ #4,A0 ;skip namePtr
MOVE.L (A0)+,(A2)+ ;vRefNum and refNum
MOVE.W (A0)+,(A2)+ ;version and permission
MOVE.L (A0)+,(A2)+ ;misc
MOVE.L (A0)+,(A2)+ ;buffer
MOVE.L (A0)+,(A3)+ ;reqCount
MOVE.L (A0)+,(A3)+ ;actCount
MOVE.W (A0)+,(A3)+ ;mode
MOVE.L (A0)+,(A3)+ ;offset
MOVE.L ioFileName(A5),A0
MOVE.L #$FF000000,D2
ST (A4)+
RTS
FinishTemplate
CLR.B (A4)
MOVE.L A0,D7 ;Check for NIL
BEQ.S NameNIL ;go mark it NIL.
ST (A4) ;Mark valid, if so.
MOVE.W #63,D1 ;D1 is max allowable chars-1.
LEA Name64,A1
MOVEQ #0,D0
MOVE.B (A0)+,D0 ;Get string length into D0.
@1 SUBQ.W #1,D0 ;Decrement length.
BMI.S @2 ;Don't stuff a char, stuff a NoOp.
MOVE.B (A0)+,(A1)+
BRA.S @3
@2 MOVE.B #NoOp,(A1)+
@3 DBRA D1,@1 ;Do it 64 times
NameNIL
MOVE.L D2,A0 ;Get the potential next address
BSR CheckA0
BCC.S @1
MOVEQ #-1,D0
MOVE.L D0,A0
@1 LEA FutureTemplate,A1
MOVE.L A0,(A1) ;Set up for next time
RTS
UAFunc Template1,Template2
DC.B If.Pos
DC.B If.Pos
DC.B ':address=',Skip+1,PrHex+6
DC.B ':rowBytes=',Skip+1,PrHex+2
DC.B ':bounds=',PrHex+4,' ',PrHex+4,' ',PrHex+4,' ',PrHex+4
DC.B ':portRect=',PrHex+4,' ',PrHex+4,' ',PrHex+4,' ',PrHex+4
DC.B If.Else
DC.B ':nextControl=',Skip+1,PrHex+6
DC.B ':owner=',Skip+1,PrHex+6
DC.B ':rect=',PrHex+4,' ',PrHex+4,' ',PrHex+4,' ',PrHex+4
DC.B ':',If.Pos,'in',End.If,'visible'
DC.B ':hilite=',PrHex+2
DC.B End.If
DC.B If.Else
DC.B If.Pos
DC.B ':destRect=',PrHex+4,' ',PrHex+4,' ',PrHex+4,' ',PrHex+4
DC.B ':viewRect=',PrHex+4,' ',PrHex+4,' ',PrHex+4,' ',PrHex+4
DC.B ':height=',PrHex+4
DC.B ':lines=',PrHex+4
DC.B If.Else
DC.B ':qLink=',Skip+1,PrHex+6
DC.B ':trap=',PrHex+4
DC.B ':cmdAddr=',Skip+1,PrHex+6
DC.B ':completion=',Skip+1,PrHex+6
DC.B ':result=',PrHex+4
UAParam Template1,0
Part1 DC 0
DCB.B 22,0
UACode Template1
UAFunc Template2,Template3
DC.B If.Pos
DC.B If.Pos
DC.B ':visRgn=',Skip+1,PrHex+6
DC.B ':clipRgn=',Skip+1,PrHex+6
DC.B ':windowKind=',PrHex+4
DC.B ':',If.Pos,'in',End.If,'visible'
DC.B ':',If.Pos,'not ',End.If,'hilited'
DC.B ':',If.Pos,'noG',If.Else,'g',End.If,'oAway'
DC.B If.Else
DC.B ':value=',PrHex+4
DC.B ':min=',PrHex+4
DC.B ':max=',PrHex+4
DC.B ':defProc=',Skip+1,PrHex+6
DC.B ':dataHandle=',Skip+1,PrHex+6
DC.B ':action=',Skip+1,PrHex+6
DC.B End.If
DC.B If.Else
DC.B If.Pos
DC.B ':selPoint=',PrHex+4,' ',PrHex+4
DC.B ':selStart=',PrHex+4
DC.B ':selEnd=',PrHex+4
DC.B ':wordBreak=',Skip+1,PrHex+6
DC.B ':clikLoop=',Skip+1,PrHex+6
DC.B If.Else
DC.B ':vRefNum=',PrHex+4
DC.B ':refNum=',PrHex+4
DC.B ':versNum=',PrHex+2
DC.B ':permission=',PrHex+2
DC.B ':misc=',Skip+1,PrHex+6
DC.B ':buffer=',Skip+1,PrHex+6
UAParam Template2,0
Part2 DC 0
DCB.B 18,0
UACode Template2
UAFunc Template3,Template4
DC.B If.Pos
DC.B If.Pos
DC.B ':strucRgn=',Skip+1,PrHex+6
DC.B ':contRgn=',Skip+1,PrHex+6
DC.B ':updateRgn=',Skip+1,PrHex+6
DC.B ':defProc=',Skip+1,PrHex+6
DC.B ':dataHandle=',Skip+1,PrHex+6
DC.B If.Else
DC.B ':refCon=',PrHex+8
DC.B End.If
DC.B If.Else
DC.B If.Pos
DC.B ':clickTime=',PrHex+8
DC.B ':clickLoc=',PrHex+4
DC.B ':caretTime=',PrHex+8
DC.B ':caretState=',PrHex+4
DC.B ':',If.Pos
DC.B If.Pos,'left'
DC.B If.Else,'center'
DC.B End.If
DC.B If.Else
DC.B If.Pos,'???'
DC.B If.Else,'right'
DC.B End.If
DC.B End.If,' justify'
DC.B If.Else
DC.B ':reqCount=',PrHex+8
DC.B ':actCount=',PrHex+8
DC.B ':newLineChar=',PrHex+2
DC.B ':posMode=',PrHex+2
DC.B ':offset=',PrHex+8
UAParam Template3,0
Part3 DC 0
DCB.B 20,0
UACode Template3
UAFunc Template4,ResetMacintosh
DC.B If.Pos
DC.B If.Pos
DC.B ':controlList=',Skip+1,PrHex+6
DC.B ':nextWindow=',Skip+1,PrHex+6
DC.B ':refCon=',PrHex+8
DC.B ':'
DC.B If.Else
DC.B ':Control '
DC.B End.If,'title'
DC.B If.Else
DC.B If.Pos
DC.B ':length=',PrHex+4
DC.B ':textH=',Skip+1,PrHex+6
DC.B ':font=',PrHex+3
DC.B ':size=',Skip+1,PrHex+2
DC.B ':port=',Skip+1,PrHex+6
DC.B ':hiHook=',Skip+1,PrHex+6
DC.B ':carHook=',Skip+1,PrHex+6
DC.B If.Else
DC.B ':Volume/File name'
DC.B End.If
DC.B End.If
DC.B If.Neg
DC.B '='
DC.B If.Neg
DC.B '"'
Name64 DCB.B 64,NoOp ;name can be up to 64 chars
DC.B '"'
DC.B If.Else
DC.B 'NIL'
UAParam Template4,0
Part4 DC 0
DCB.B 22,0
DC 0
UACode Template4
UAFunc StackLook,StackCrawl
DC.B 'Stack addresses {'
DC.B If.Pos
DC.B PrHex+6
DC.B ' (',Recognize,Skip+1,')' ; ? Recognize bug
DC.B If.Else
DC.B Skip+7
DC.B End.If
DC.B '} (addr)',Colon
DC.B If.Pos
DC.B PrHex+6
DC.B If.Else
DC.B If.Neg
DC.B 'SP'
UAParam StackLook,%00011
LONG -1
LONG -1
LONG -1
UACode StackLook
MOVE.L A0,A4
TST.B D7 ;Check the number of parameters.
BNE.S Look
CancelLook
MOVEQ #-1,D0 ;If none, cancel things (RA6).
MOVE.L D0,(A4)+
MOVE.L D0,(A4)+
MOVE.L D0,(A4)+
RTS
Look
MOVE.L D0,D1 ;Otherwise check validity.
BSR.S CheckStackD1.A0
BCS.S CancelLook ;Invalid also means cancel.
ADDQ.L #2,D0 ;Advance D0.
MOVE.L (A0),D1
BSR CheckD1.A0
BCS.S Look ;Keep looking for a valid value.
CMP.L ROMBase,A0
BHS.S StopLooking
CMP.L RealMemTop,A0
BHS.S Look ;Keep looking for a valid value.
StopLooking
MOVE.L A0,V.A5 ;Put the contents in the monitor's V.
MOVE.L A0,(A4)
MOVE.L A0,4(A4)
MOVE.L D0,D1
BSR CheckStackD1.A0
BCS.S @3
MOVE.L A0,8(A4) ;Next SP.
RTS
@3 MOVE.W #$FF00,8(A4) ;No SP.
RTS
CheckStackD1.A0
BSR.S CheckD1.A0
BCS.S @1
MOVE.L CurStackBase,D7 ;Get the stack base.
NEG.L D7
ADD.L A0,D7 ;Set the carry if D1>CurStackBase
@1 RTS
CheckD1.A0 ;A more thorough check based on CheckA0
AND.L Lo3Bytes,D1
MOVE.L D1,A0
BSR CheckA0
BCS.S @1
ADD.L #-$500000,D1 ;Set the carry if D1>500000
@1 RTS
UAFunc StackCrawl,GetResource
DC.B 'Stack crawl {'
DC.B If.Pos
DC.B 'PC=',PrHex+6
DC.B ' (',Recognize,Skip+1,')' ; ? Recognize bug
DC.B If.Else
DC.B Skip+7
DC.B End.If
DC.B '} (addr)',Colon
DC.B If.Pos
DC.B PrHex+6
DC.B If.Else
DC.B If.Neg
DC.B 'RA6'
UAParam StackCrawl,%00011
LONG -1
LONG -1
LONG -1
UACode StackCrawl
MOVE.L A0,A4
TST.B D7 ;Check the number of parameters
BNE.S Crawl
CancelCrawl
MOVEQ #-1,D0 ;If none, cancel things (RA6)
MOVE.L D0,(A4)+
MOVE.L D0,(A4)+
MOVE.L D0,(A4)+
RTS
Crawl
MOVE.L D0,D1 ;Otherwise check validity
BSR.S CheckD1.A0
BCS.S CancelCrawl ;Invalid also means cancel
MOVE.L A0,N.A5 ;Put the A6 in the monitor's N
MOVE.L 4(A0),D1
BSR CheckD1.A0
BCC.S @1
ST (A4) ;Invalid PC
BRA.S @2
@1 MOVE.L A0,V.A5 ;Put the PC in the monitor's V
MOVE.L A0,(A4)
MOVE.L A0,4(A4)
@2 MOVE.L D0,A0 ;De-ref that other thing.
MOVE.L (A0),D1
BSR CheckD1.A0
BCS.S @3
MOVE.L A0,8(A4) ;Next A6
RTS
@3 MOVE.W #$FF00,8(A4) ;No A6
RTS
UAFunc GetResource,ShowScreen
DC.B 'Load resource {'
DC.B If.Pos
DC.B 'at ',PrHex+6
DC.B If.Else
DC.B Skip+3
DC.B End.If
DC.B '} (type ID)',Colon
DC.B If.Pos
DC.B Skip+1,'''',PrASCII+4,'''',' ',PrHex+4
UAParam GetResource,%00101
LONG -1
DC $FF00
LONG 0
DC 0
UACode GetResource
TST.B D7
BNE.S @1
MOVEQ #-1,D0
MOVE.L D0,(A0)+
MOVE.B D0,(A0)+
RTS
@1 CLR.B 4(A0)
BSR ExiTMON.
LEA A0.A5,A1 ;Save Monitor's A0 through A2.
MOVE.L (A1),-(A2)
MOVE.L A5,(A1) ;Store A5 in Monitor's A2.
MOVE.L -(A1),-(A2)
MOVE.L A0,(A1) ;Store a pointer to GetResource's user data area in
MOVE.L -(A1),-(A2) ;Monitor's A1.
LEA D0.A5,A1
MOVE.L (A1),-(A2) ;Save Monitor's D0 through D2.
MOVE.L -(A1),-(A2)
MOVE.L D1,(A1) ;Store D1 in Monitor's D1.
MOVE.L -(A1),-(A2)
MOVE.L D0,(A1) ;Store D0 in Monitor's D0.
LEA LoadRes.,A0
BRA ExiTMON
LoadRes.
MOVE.L D0,6(A1) ;Save the data given to this routine.
MOVE.W D1,10(A1)
CLR.L -(SP) ;Prepare to call _GetResource.
MOVE.L D0,-(SP)
MOVE.W D1,-(SP)
MOVE.W ResErr,D2 ;Save the current resource manager error.
_GetResource ;Load the resource.
MOVE.W D2,ResErr
ST (A1) ;Assume that an error occurred.
MOVE.L (SP)+,A0
MOVE.L A0,D0 ;If the handle is NIL, exit.
BEQ.S @1
MOVE.L (A0),D0 ;If it isn't NIL, give the dereferenced handle.
MOVE.L D0,(A1)
CLR.B (A1)
MOVE.L (A1),V.A2 ;Also store the position in V.
@1 MOVEM.L (SP)+,D0/D1/D2/A0/A1/A2
TRAPMon 'OK'
UAFunc ShowScreen,ResetMacintosh
DC.B 'Click mouse outside TMON'
UAParam ShowScreen,%00001
UACode ShowScreen
BSR.S ExiTMON. ;Prepare to exit the Monitor.
LEA ShowScreen.,A0
BRA.S ExiTMON
ShowScreen.
TST.B MBState ;Wait until the mouse button is released.
BPL.S ShowScreen.
@1 TST.B MBState ;Wait until it is pressed again.
BMI.S @1
TRAPMon 'OK' ;Go back to the Monitor.
ExiTMON
MOVE.L A2,SP.A5
MOVE.L A0,-(A3)
JMP _ExiTMON
ExiTMON.
MOVE.L SP.A5,A2 ;Prepare the PC and SR to exit the Monitor.
LEA PC.A5,A3
MOVE.L (A3)+,-(A2)
MOVE.W (A3),-(A2)
MOVE.W #$2000,(A3)
RTS
UAFunc ResetMacintosh,0
DC.B If.Pos
DC.B 'Finder'
DC.B If.Else
DC.B 'Shut down'
DC.B End.If
DC.B ' (confirm)'
UAParam ResetMacintosh,%00011
DC.B 0
UACode ResetMacintosh
TST.B D7 ;If just a RETURN was pressed, toggle
BNE.S @1
NOT.B (A0)
RTS
@1 TST.B (A0)
BPL.S Finder
ShutDown
SUB.W #ioQElSize,SP ;Eject disks in both drives and reset.
MOVE.L SP,A0
CLR.L ioVNPtr(A0)
MOVE.L VCBQHdr+qHead,A1 ;Get the first Drive Queue entry
@2 MOVE.L A1,D0
BEQ.S @1
MOVE.W VCBVRefNum(A1),ioVRefNum(A0)
_Eject ;Eject a volume
_UnmountVol
MOVE.L qLink(A1),A1 ;Advance along queue
BRA.S @2
@1 MOVE.L ROMBase,A0 ;Get the restart address
ADD #10,A0 ;from the ROM.
JMP (A0)
Finder
BSR ExiTMON. ;Prepare to exit the Monitor.
LEA Finder.,A0
BRA ExiTMON
Finder.
MOVE.L CurrentA5,A5 ;Set up globals
MOVE.L CurStackBase,SP
CloseResFiles
MOVE.L TopMapHndl,A0 ;Check if we are done yet
CMP.L SysMapHndl,A0
BEQ.S CloseOtherFiles
MOVE.L (A0),A0 ;Deref the map pointer
MOVE.W resFileID(A0),-(SP) ;And get the file ID to close it
_CloseResFile ;Close resource files
BRA.S CloseResFiles
CloseOtherFiles
MOVE.W FSFCBLen,D3 ;Get the FCB length in D3
BPL.S NotMFS
MOVE.W #30,D3 ;MFS FCB length is 30
NotMFS
SUB.W #ioQElSize,SP ;Close non-resource files
MOVE.L SP,A0
MOVE.L FCBSPtr,A1 ;Point to FCBs
MOVE.W (A1),D2 ;Get size of FCBs
MOVEQ #2,D1 ;Start with the first file
CheckFile
CMP.W D2,D1
BHS.S DidAllFiles
CMP.W SysMap,D1 ;Do NOT close the System resource file
BEQ NextFile
TST.L fcbFlNm(A1,D1.W) ;Check if the file is used
BEQ.S NextFile
MOVE.W D1,ioRefNum(A0) ;Close the file
_Close
NextFile
ADD.W D3,D1 ;Advance to another FCB
BRA.S CheckFile
DidAllFiles
_ExitToShell
;The 2nd user area screen starts here (label, A000 trap and heap)
UAFunc LabelTableSet,LAddRemove
DC.B 'Label table {'
DC.B If.Pos
DC.B Skip+1,PrHex+3,' labels} (nLabels [loc])',Colon
DC.B Skip+2,PrHex+3,' ',Skip+1,PrHex+6
DC.B If.Else
DC.B '} (nLabels [loc])'
UAParam LabelTableSet,%00111
DC $FF00
NumLabels DC 0
LabelEnabled DC $FF00
LabelCapacity DC 0
LabelTable LONG 0
DC 0
UACode LabelTableSet
MOVE.L D1,D2 ;Shift the parameters by one and fall into RecordTableSet.
MOVE.L D0,D1
MOVEQ #0,D0
ADDQ.B #1,D7
BSR RecordTableSet ;Use the RecordTableSet routine to do most of the work.
LEA LabelEnabled,A0
MOVE.W (A0),-4(A0)
RTS
UAFunc LAddRemove,LabelLoad
DC.B 'Label add/remove {'
DC.B If.Pos
DC.B Skip+1,'"',PrASCII+8,'"',' '
DC.B If.Neg
DC.B 'removed'
DC.B If.Else
DC.B 'added '
DC.B If.Neg
DC.B 'rel ''',PrASCII+4,''''
DC.B End.If
DC.B End.If
DC.B End.If
DC.B '} (lbl [adr [end]])'
UAParam LAddRemove,$80+%11101 ;$80 means the first 2 are a label
DC $FF00
LONG 0
LONG 0
DC 0
LONG 0
UACode LAddRemove
AND.L Lo3Bytes,D2 ;Clear the high bytes of the addresses.
AND.L Lo3Bytes,D3
LAddRemove.Map
MOVE.L D7,D6 ;If bit 31 of D7 is set, no checks are made.
MOVE.L A0,A3 ;Save A0.
CLR.W (A3)+ ;Initialize results.
MOVE.L D0,(A3)+
MOVE.L D1,(A3)+
TST.W D6 ;If no parameters, do nothing.
BEQ.S @10
MOVE.B LabelEnabled,D7 ;If there is no table of labels, do nothing.
BMI.S @10
MOVE.B _Inhibits,D7 ;Get the value of _Inhibits.
SWAP D7
MOVE.L D2,D4 ;Save D2 and D3.
MOVE.L D3,D5
MOVEQ #-1,D2
BSR LabelFind. ;Is the label present in the table?
TST.L D0
BNE.S @2 ;NO.
MOVE.L A0,D0 ;YES. Is it in the user area table?
BEQ.S @10 ;YES.
SUBQ.W #2,D6 ;NO. Should it be removed?
BNE.S @3 ;NO. Change its value.
LEA NumLabels,A1 ;YES. Remove it.
SUBQ.W #1,(A1)
MOVEQ #0,D0 ;Call _BlockMove to shift the remaining labels
MOVE.W (A1),D0 ;forward.
ASL.W #4,D0
MOVE.L A0,A1
ADD.W #16,A0
ADD.L LabelTable,D0
MOVE.L D0,A2
SUB.L A1,D0
BEQ.S @1
_BlockMove
@1 CLR.L (A2)+ ;Clear the last label.
CLR.L (A2)+
CLR.L (A2)+
CLR.L (A2)+
ST (A3) ;Tell the user that the label was removed.
RTS
@10 ST -10(A3) ;Return an error.
RTS
@2 SUBQ.W #2,D6 ;If the label was not found, and no more parameters
BEQ.S @10 ;were given, return an error.
LEA NumLabels,A0 ;If can't insert another label because the table is
MOVE.W (A0),D2 ;full, return an error.
CMP.W LabelCapacity,D2
BCC.S @10
ADDQ.W #1,(A0)
MOVE.L LabelTable,A0
ASL.W #4,D2
ADD.W D2,A0
@3 MOVE.L A0,-(SP) ;Save the location to contain the next label.
LEA _Inhibits,A0
MOVE.B (A0),-(SP) ;Set all _Inhibits flags except searching resources
ORI.B #%00110100,(A0) ;and the master switch.
SUB.W #24,SP ;Allocate space for _Recognize's information.
MOVE.L SP,A2
ADDQ.W #1,A2 ;Put the data on a word boundary for easier access.
MOVEM.L D4/A0,-(SP)
MOVE.L D4,D2
MOVEQ #-1,D0 ;If there is a third parameter, assume that
SUBQ.W #1,D6 ;_Recognize failed.
BNE.S @4
JSR _Recognize ;Check if the address given in D4 was in a resource.
@4 MOVEM.L (SP)+,D4/A0
CLR.W (A3)
TST.B D0
BNE.S @11 ;NO.
ADDQ.W #2,SP ;YES. Extract the resource type, ID, and internal
MOVE.L (SP)+,D4 ;offset.
ST 1(A3)
MOVE.L D4,2(A3)
BSR.S @20
MOVE.W D0,D5
SWAP D5
ADDQ.W #6,SP
BSR.S @20
SUB.W #12,SP
MOVE.W D0,D5
BRA.S @13
@11 TST.L D6 ;If bit 31 of D6 was set, do no checks.
BMI.S @13
TST.W D6 ;Calculate the ending address from the starting one
BNE.S @12 ;unless the ending address is already given.
MOVE.L D4,D5
ADD.L #$800,D5 ;Default is $800+starting address.
@12 CMP.L D4,D5 ;Ending address must be greater than the starting
BHI.S @13 ;address.
MOVE.L D4,D5
ADDQ.L #1,D5
@13 ADD.W #24,SP ;Deallocate the stack space.
MOVE.B (SP)+,(A0) ;Restore _Inhibits.
MOVE.L (SP)+,A0 ;Get the address into which the label is to be
MOVE.L D4,(A0)+ ;stored.
MOVE.L D5,(A0)+ ;Store the label data.
MOVE.L -8(A3),(A0)+
MOVE.L -(A3),(A0)+
RTS
@20 MOVEQ #3,D2 ;Extract a word from a four-digit hexadecimal
LEA 4(SP),A1 ;number on the stack.
@21 MOVE.B (A1)+,D1
SUB.B #'0',D1
CMP.B #10,D1
BCS.S @22
SUBQ.B #7,D1
@22 ASL.W #4,D0 ;Store the result in D0.
ADD.B D1,D0
DBRA D2,@21
LabelLoadRTS RTS
UAFunc LabelLoad,TrapRecord
DC.B 'Label file load'
UAParam LabelLoad,%00001
UACode LabelLoad
MOVE.B LabelEnabled,D0 ;If there is no table of labels, do nothing.
BMI.S LabelLoadRTS
BSR ExiTMON. ;Prepare to exit the Monitor.
LEA LabelLoad.,A0
BRA ExiTMON
;
;This subroutine is used to load label maps into memory.
;
LabelLoad.
A6TypeList EQU -4
A6Reply EQU A6TypeList-64-rName
A6IO EQU A6Reply-ioQElSize
A6Size EQU A6IO
typeList EQU A6TypeList(A6) ;Type list for _SFGetFile.
reply EQU A6Reply(A6) ;Reply record from _SFGetFile.
param EQU A6IO(A6) ;File I/O queue element.
sfGood EQU A6Reply+rGood(A6)
sfType EQU A6Reply+rType(A6)
sfVolume EQU A6Reply+rVolume(A6)
sfVersion EQU A6Reply+rVersion(A6)
sfName EQU A6Reply+rName(A6)
scratch64 EQU reply ;At least 64 bytes will be here.
MOVEM.L D0-D7/A0-A5,-(SP) ;Save registers.
MOVE.L CurrentA5,A5 ;Get A5 for QuickDraw.
LINK A6,#A6Size
MOVE.L #'TEXT',typeList
MOVE.L #$00440052,-(SP) ;where = (82,68).
CLR.L -(SP) ;Prompt parameter - not used.
CLR.L -(SP) ;No fileFilter.
MOVE.W #1,-(SP) ;One type.
PEA typeList ;Type list.
CLR.L -(SP) ;No dlgHook.
PEA reply ;reply record.
_SFGetFile
LEA A5.TMON,A5 ;Get the Monitor's A5.
TST.B sfGood ;Was cancel pressed?
BEQ.S @20 ;YES. Do nothing.
LEA param,A0
LEA sfName,A1 ;Prepare the parameter block for _Open.
MOVE.L A1,ioFileName(A0)
MOVE.W sfVolume,ioVRefNum(A0)
MOVE.W #1,ioFileType(A0) ;Clear ioFileType and set ioPermssn to read.
CLR.L ioOwnBuf(A0) ;No special file buffer.
_Open ;Open the text file.
BNE.S @20 ;If errors, do nothing.
MOVEQ #0,D6 ;Get the next identifier.
BRA.S @2
@1 ADDQ.W #8,SP
@2 MOVE.L #' ',-(SP) ;Initially clear all eight characters to spaces.
MOVE.L (SP),-(SP)
MOVEQ #0,D3
@3 BSR @40 ;Get the next character.
BEQ.S @1 ;If this is not a normal legal ASCII character,
CMP.B #'=',D0 ;restart.
BEQ.S @4 ;If this is the equal sign, proceed.
CMP.B #8,D3 ;Put this character onto the string, but keep only
BCC.S @3 ;the first eight characters found.
MOVE.B D0,0(SP,D3.W)
ADDQ.W #1,D3
BRA.S @3
@20 UNLK A6
MOVEM.L (SP)+,D0-D7/A0-A5 ;Exit with an error.
TRAPMon 'Bad load'
@4 TST.W D3 ;If the identifier was null, try again.
BEQ.S @1
MOVEM.L (SP)+,D2/D3
BSR.S @60 ;Get a decimal number (the segment number).
BCS.S @2 ;If error, try again.
CMP.B #':',D0 ;The next character must be a colon.
BNE.S @2
MOVE.W D1,D4 ;Save the segment number in D4.
BSR.S @30 ;Get the offset.
BCS.S @2
AND.L Lo3Bytes,D1 ;Clear the high byte of the address.
MOVEM.L D5-D7/A2-A4/A6,-(SP) ;Save registers for LAddRemove.
MOVE.L D2,D0
EXG D1,D3
TST.W D4 ;If the segment number was zero, create an absolute
BNE.S @10 ;reference.
MOVE.L D3,D2
ADD.L #$800,D3 ;Let the ending address equal the starting address
BRA.S @11 ;plus $800.
@10 MOVE.L #'CODE',D2 ;If the segment number was not zero, create a
SWAP D3 ;'CODE' resource-relative reference.
MOVE.W D4,D3
SWAP D3
ADDQ.W #4,D3 ;Skip the four bytes at the segment beginning.
@11 MOVEQ #9,D7 ;Set bit 31 of D7.
ROR.L #1,D7
LEA scratch64,A3 ;Provide a scratch area for LAddRemove.
BSR LAddRemove.Map ;Add the label. There is no error checking.
MOVEM.L (SP)+,D5-D7/A2-A4/A6
BRA @2
@30 MOVEQ #0,D5 ;Attempt to get a hexadecimal number. D5 is zero
MOVEQ #0,D1 ;when there are no digits. D1 has the number.
@31 BSR.S @40 ;Get the next character and make it into a number.
MOVE.B D0,D7 ;D7 is destroyed.
SUB.B #'0',D7
BCS.S @32
CMP.B #10,D7
BCS.S @33
CMP.B #17,D7
BCS.S @32
SUBQ.B #7,D7
CMP.B #$10,D7
BCC.S @32
@33 LSL.L #4,D1 ;If successful, append it to the number. There is
ADD.B D7,D1 ;no overflow checking.
MOVEQ #1,D5
BRA.S @31
@32 SUBQ.B #1,D5 ;Set the carry if no digits were found.
RTS
@60 MOVEQ #0,D5 ;Attempt to get a decimal number. D5 is zero
MOVEQ #0,D1 ;when there are no digits. D1 has the number.
@61 BSR.S @40 ;Get the next character and make it into a number.
MOVE.B D0,D7 ;D7 is destroyed.
SUB.B #'0',D7
BCS.S @62
CMP.B #10,D7
BCC.S @62
@63 MOVEQ #0,D0 ;Make a number in D0.
MOVE.B D7,D0
LSL.L #1,D1 ;If successful, append it to the number. There is
ADD.L D1,D0 ;no overflow checking.
LSL.L #2,D1
ADD.L D0,D1
MOVEQ #1,D5
BRA.S @61
@62 SUBQ.B #1,D5 ;Set the carry if no digits were found.
RTS
@40 TST.B D6 ;If the end of file was encountered, go exit now.
BNE.S @50
LEA param,A0
LEA -1(A6),A1
MOVE.L A1,ioBuffer(A0)
MOVEQ #1,D0
MOVE.L D0,ioReqCount(A0) ;Request a read of one byte.
CLR.W ioPosMode(A0) ;Read from the mark.
_Read
BMI.S @41 ;If error, pass back a zero and exit on the next
MOVE.B -1(A6),D0 ;call to @40 (to finish a number if necessary).
CMP.B #' ',D0
BEQ.S @40 ;Ignore spaces.
BCS.S @42
CMP.B #$7F,D0 ;Convert characters below $20 and above $7E to 0.
BCS.S @43
BRA.S @42
@41 MOVEQ #1,D6 ;Set the end of file flag.
@42 MOVEQ #0,D0
@43 TST.B D0
RTS
@50 _Close ;Close the file.
UNLK A6
MOVEM.L (SP)+,D0-D7/A0-A5 ;Exit with no error.
TRAPMon 'OK'
UAFunc TrapRecord,RecordTableSet
DC.B 'Trap record (t0 [t1 [PC0 PC1]])',Colon
DC.B If.Pos
DC.B Skip+1,DisAsm0,' ',DisAsm0
DC.B If.Pos
DC.B ' ',PrHex+6,' ',Skip+1,PrHex+6
UAParam TrapRecord,%10111
TrapRList DC $FF00
DC 0,0
LONG -1
LONG -1
ADDR RecordHook
UACode TrapRecord
BRA A000
UAFunc RecordTableSet,TrapScramble
DC.B 'Record {'
DC.B If.Neg
DC.B Skip+1,PrHex+4,' new traps'
DC.B If.Else
DC.B Skip+3
DC.B End.If
DC.B '} (fullStop nMsg [loc])',Colon
DC.B If.Pos
DC.B PrHex+1,' ',PrHex+3,' ',Skip+1,PrHex+6
UAParam RecordTableSet,%01101
DC 0
RecordData DC 0
DC $FF00
DC 0
LONG 0
DC 0
DC 0
UACode RecordTableSet
ADDQ #2,A0
MOVE.L A0,A2
CLR.W (A2)+ ;Always set the number of new traps to zero.
TST.B 8(A2) ;If a block was previously allocated, deallocate it
BEQ.S @1 ;now.
MOVE.L 4(A2),A0
MOVE.L D0,-(SP)
_DisposPtr
MOVE.L (SP)+,D0
CLR.B 8(A2) ;Don't deallocate it again.
@1 MOVE.L A2,A1
CMP.B #2,D7 ;If not enough parameters present, exit.
BCS.S @10
AND.W #$7FF,D1 ;Can't have a zero-message storage area.
BEQ.S @10
CLR.B (A1)+ ;Set the recording master switch.
TST.L D0
SNE (A1) ;Initialize the overflow flag.
NEG.B (A1)+
MOVE.W D1,(A1)+ ;If data given, store it.
MOVEQ #0,D0
MOVE.W D1,D0
ASL.W #4,D0
SUBQ.W #3,D7 ;If address given, done.
BEQ.S @6 ;Otherwise, allocate a block of the appropriate size
_NewPtr,Sys+Clear ;in the system Heap.
BNE.S @10 ;If error, turn off the master switch.
ST 4(A1) ;Set the heap block allocated flag.
@9 MOVE.L A0,(A1) ;Store the address of the block.
MOVE.L A0,V.A5 ;Store it also in the V variable.
RTS
@6 MOVE.L D2,A0
MOVE.L A0,A3 ;Clear the block if it was manually allocated.
LSR.W #2,D0
BRA.S @8
@7 CLR.L (A3)+
@8 DBRA D0,@7
BRA.S @9
@10 ST (A2) ;Clear the master switch.
RTS
RecordEnter
LEA RecordData+2,A0 ;Prepare to use the swapping routine to move the
MOVE.W (A0)+,D0 ;latest traps to the beginning.
BMI.S @1
MOVEQ #0,D1 ;Otherwise use SlowScramble to shift the message table
MOVE.W (A0)+,D1 ;so that the latest message is at the top.
ASL.W #4,D1 ;D1 now contains the size of the table.
MOVE.L (A0)+,A5 ;A5 contains its beginning.
MOVEQ #0,D4
MOVE.W 2(A0),D4 ;D4 contains the offset to the current storing
BEQ.S @1 ;position in the table.
ASL.W #4,D4
SUB.L D4,D1 ;D1 now contains the offset from D4 to the end.
MOVE.L A5,A4
ADD.L D4,A4 ;A4 now points to the current storing position.
BSR SlowScramble ;Use the routine from ScrambleHeap to expedite shifting.
@1
LEA RecordData,A0 ;Check if there were any?
TST.W (A0)
SNE -2(A0)
RTS
RecordExit
LEA RecordData,A0 ;Clear the number of messages every time exiting
CLR.W (A0) ;the Monitor.
CLR.W 12(A0)
RTS
UAFunc TrapScramble,HeapInfo
DC.B 'Trap {heap check'
DC.B If.Neg
DC.B ', scramble'
DC.B End.If
DC.B If.Neg
DC.B ', purge'
DC.B End.If
DC.B '} (zone#)',Colon
DC.B If.Pos,PrHex+1
UAParam TrapScramble,%00011
CheckOnly DC.B $FF
PurgeAlso DC.B 0
TrapSList DC.B $80
CurrentHeap DC.B 0
DC $1E,$27 ;_NewPtr _ReallocHandle
LONG -1
LONG -1
ADDR ScrambleHook
UACode TrapScramble
TST.B D7 ;If no number was given, go to the second part.
BEQ.S @2
TST.L D0 ;Choose the heap and enable the scramble.
BEQ.S @1
MOVEQ #1,D0
@1 MOVE.W #.ScrambleNow-A,.TrapScramble-A(A2)
CLR.B ScrambleNowErr-A(A2)
ST HeapInfoDisp-A(A2)
CLR.B HeapInfoHeap-A(A2)
MOVE.W D0,2(A0)
BRA.S @3
@2 MOVE.W #.HeapInfo-A,.TrapScramble-A(A2)
BSET #7,2(A0) ;If the ScrambleHeap is enabled, disable it.
BEQ.S @3 ;Otherwise,
NOT.B 1(A0) ;allow the user to pick a combination of two flags.
BMI.S @3
NOT.B (A0) ;Flip the heap flag.
@3 MOVE.W (A0),CheckOnly.-A(A2) ;Notify the ScrambleNow function.
BRA A000OnOff ;Check the master A000 intercept switch.
UAFunc HeapInfo,TrapDiscipline
DC.B 'Heap {'
DC.B If.Pos
DC.B 'free=',PrHex+6
DC.B Skip+1,' max=',PrHex+6
DC.B Skip+1,' grow=',PrHex+6
DC.B If.Else
DC.B Skip+3,Skip+4,Skip+4
DC.B End.If
DC.B '} (zone#)',Colon
DC.B If.Neg
DC.B PrHex+1
UAParam HeapInfo,%00011
HeapInfoDisp LONG -1
LONG -1
LONG -1
HeapInfoHeap DC 0
UACode HeapInfo
TST.B D7
BNE.S @10
ST (A0)
CLR.B 12(A0)
RTS
@10 MOVE.L A0,A4 ;Save a pointer to the variables.
ADD.W #12,A0
ST (A0)+
TST.L D0
SNE (A0) ;Store the given heap zone.
NEG.B (A0)
BSR GetZone ;Get the appriopriate heap zone.
BSR PurgeHeap ;Get the maximum possible block size.
MOVE.L 12(A6),(A4)+ ;Get the theoretical number of free bytes.
MOVE.L D0,(A4)+ ;Get the maximum allowable block size.
MOVE.L A0,D0
BEQ.S @2 ;If this isn't the application heap zone, exit.
MOVE.L SP.A5,D0 ;Get the SP.
AND.L Lo3Bytes,D0
SUB.L MinStack,D0 ;Pick either the application limit or SP-minimum
CMP.L ApplLimit,D0 ;stack size, whichever is less.
BCS.S @1
MOVE.L ApplLimit,D0
@1 SUB.L HeapEnd,D0 ;Subtract the end of heap from that.
@2 MOVE.L D0,(A4)+ ;Get the maximum grow area.
RTS
UAFunc ScrambleNow,TrapDiscipline
DC.B 'Check'
DC.B If.Neg
DC.B ', scramble'
DC.B End.If
DC.B If.Neg
DC.B ', purge'
DC.B End.If
DC.B ' now {'
DC.B If.Neg
DC.B 'heap error'
DC.B End.If
DC.B '}'
UAParam ScrambleNow,%00001
CheckOnly. DC.B $FF
PurgeAlso. DC.B $00
ScrambleNowErr DC.B 0 ;Was there an error?
UACode ScrambleNow
BSR ScrambleHeap
LEA ScrambleNowErr,A0
TST.L D0
SNE (A0) ;Set if there is an error.
RTS
UAFunc TrapDiscipline,TrapChecksum
DC.B 'Trap discipline (t0 [t1 [PC0 PC1]])',Colon
DC.B If.Pos
DC.B Skip+1,DisAsm0,' ',DisAsm0
DC.B If.Pos
DC.B ' ',PrHex+6,' ',Skip+1,PrHex+6
UAParam TrapDiscipline,%10111
TrapDList DC $FF00
DC 0,0
LONG -1
LONG -1
ADDR DisciplineHook
UACode TrapDiscipline
BRA A000
UAFunc TrapChecksum,Checksum
DC.B 'Trap checksum (t0 [t1 [PC0 PC1]])',Colon
DC.B If.Pos
DC.B Skip+1,DisAsm0,' ',DisAsm0
DC.B If.Pos
DC.B ' ',PrHex+6,' ',Skip+1,PrHex+6
UAParam TrapChecksum,%10111
TrapCList DC $FF00
DC 0,0
LONG -1
LONG -1
ADDR ChecksumHook
UACode TrapChecksum
BRA A000
UAFunc Checksum,TrapIntercept
DC.B 'Checksum (bgn end) {',PrHex+4,'}',Colon
DC.B Skip+1,PrHex+6,' ',Skip+1,PrHex+6
UAParam Checksum,%00100
ChecksumValue DC 0
LONG $400000
LONG $40FFFF
UACode Checksum
AND.L Lo3Bytes,D0
AND.L Lo3Bytes,D1
MOVEM.L D0/D1,2(A0) ;Save the addresses.
BSR.S Checker ;Calculate the checksum.
MOVE.W D2,(A0) ;Store the checksum.
RTS
Checker
SUB.L D0,D1 ;End must not be less than start.
BLT.S @2
MOVE.L D0,A1
@1 ADD.B (A1)+,D2 ;Add another byte and shift.
ROR.W #1,D2
DBRA D1,@1
SUB.L val10000,D1 ;This is the outer checksum loop.
BCC.S @1
@2 RTS
ChecksumInit
LEA ChecksumValue,A0
MOVEM.L 2(A0),D0/D1
BSR.S Checker
MOVE.W D2,(A0)
RTS
UAFunc TrapIntercept,TrapSignal
DC.B 'Trap intercept (t0 [t1 [PC0 PC1]])',Colon
DC.B If.Pos
DC.B Skip+1,DisAsm0,' ',DisAsm0
DC.B If.Pos
DC.B ' ',PrHex+6,' ',Skip+1,PrHex+6
UAParam TrapIntercept,%10111
TrapIList DC $FF00
DC 0,0
LONG -1
LONG -1
ADDR InterceptHook
UACode TrapIntercept
BRA A000
UAFunc TrapSignal,0
DC.B 'Trap signal (t0 [t1 [PC0 PC1]])',Colon
DC.B If.Pos
DC.B Skip+1,DisAsm0,' ',DisAsm0
DC.B If.Pos
DC.B ' ',PrHex+6,' ',Skip+1,PrHex+6
UAParam TrapSignal,%10111
TrapGList DC 0
DC $170,$171 ;_GetNextEvent,_EventAvail
LONG -1
LONG -1
ADDR SignalHook
UACode TrapSignal
BRA A000
;####################################
;## ##
;## A000 hook controller section ##
;## ##
;####################################
;
;This routine is an "A000 hook controller" of the user area. It examines the parameter lists TrapDList,
;TrapSList, TrapCList, TrapIList, TrapRList, and TrapGList and checks if they contain routines that
;should be executed. If so, the routine is called (the routine's address is contained in the last
;word of its parameter list). If the routine does not detect any errors, it should return 0 in
;D0.W; otherwise, it should return an offset into the user area, which will be called to display the
;error message while returning to the Monitor.
;
;The routines called must preserve all registers except D0, D1, A0, and A1. They may use A000 traps
;without fear of reentrancy problems, as the Monitor's A000 hook is disabled for the duration of
;their execution. The interrupt button is also disabled, and the interrupt level is set to 7.
;
;Upon entry D0.W contains the trap word stripped to the 9 least significant bits and A0 contains
;the address of the trap word.
;
;Beware: Any 68000 exceptions like address errors or illegal instructions will have the same
;effect as pressing command-interrupt because the Monitor will think that the error occurred in
;its code.
;
A000Hook MOVEM.L D0/D1/A0/A1,-(SP) ;Save 4 registers.
MOVE.L 10+4*4(SP),D0 ;Get the A000 trap address.
AND.L Lo3Bytes,D0 ;Clear the high PC byte.
MOVE.L D0,A0
MOVE.W (A0),D0
AND.W #$09FF,D0 ;Get the trap number into D0.
BCLR #11,D0
BNE.S @1
AND.W #$00FF,D0 ;Clear the eighth bit for OS traps.
@1 LEA TrapRList,A1 ;Check the five routines that have A000 hooks if
BSR.S @10 ;they want to be executed.
LEA TrapSList,A1
BSR.S @10
LEA TrapDList,A1
BSR.S @10
LEA TrapCList,A1
BSR.S @10
LEA TrapIList,A1
BSR.S @10
LEA TrapGList,A1
BSR.S @10
MOVEM.L (SP)+,D0/D1/A0/A1 ;If everything is fine, exit.
@2 RTS
@10 TST.W (A1)+
BMI.S @2
CMP.W (A1)+,D0 ;Is it in the specified range?
BCS.S @2
CMP.W (A1)+,D0
BHI.S @2
TST.B (A1) ;YES. Was a PC range specified?
BMI.S @11 ;If not, do the function.
CMP.L (A1),A0 ;YES. Is the PC in the specified range?
BCS.S @2
CMP.L 4(A1),A0
BHI.S @2
@11 MOVEM.L D0/A0,-(SP) ;If everything was successful, call the subroutine.
BSR.S FlipBit
MOVE.W 8(A1),D1
LEA MonExecuting,A1 ;Find the address of MonExecuting.
MOVE.B (A1),-(SP) ;To avoid re-entering make the Monitor think that
MOVE.B #$6B,(A1) ;it is executing.
LEA A,A1
JSR 0(A1,D1.W)
LEA MonExecuting,A1 ;Find the address of MonExecuting.
MOVE.B (SP)+,(A1)
BSR.S FlipBit
TST.W D0 ;Check the return code.
BNE.S @12 ;If nonzero, show an error.
MOVE #@13-A,D0
MOVE.B UserInform,D1 ;Check UserInform.
BMI.S @12 ;If an interrupt took place, fall into the Monitor.
MOVEM.L (SP)+,D0/A0 ;Otherwise exit.
MOVE.L nasty0,0 ;Trash location zero.
RTS
@13 TRAPMon 'Interrupt'
@12 ADD.W #12,SP ;Dispose the return address and D0, D1, and A1.
MOVE.L 4+4*4(SP),4*4(SP)
LEA A,A0
LEA (A0,D0.W),A0 ;Fall into the Monitor with the appropriate message.
MOVE.L A0,4+4*4(SP)
MOVEM.L (SP)+,D0/D1/A0/A1/A5
RTS ;Jump to the appropriate TRAP #$F instruction.
;This routine flips a bit in the upper left corner.
FlipBit
MOVE.B #1,CrsrBusy ;Mark the cursor busy.
CMP.W #$A700,CrsrAddr+2 ;Is the cursor in the upper left?
BNE.S NoCursorFlip
CursorFlip
BCHG #7,CrsrSave ;Flip the bit in the area under the cursor.
NoCursorFlip
BCHG #7,$3FA700 ;Flip the bit on the screen.
CLR.B CrsrBusy ;The cursor isn't busy any more.
RTS
;This routine turns the A000 subhooks on and off.
A000
SUBQ.B #1,D7
BCS.S @4 ;No arguments given. Delete the intercepting
BNE.S @1 ;subroutine.
MOVE.W D0,D1 ;If one argument is given, the second argument
@1 AND.W #$1FF,D0 ;is set to the first one.
AND.W #$1FF,D1
CMP.W D0,D1
BCC.S @2 ;Make sure D0<=D1.
EXG D0,D1
@2 CLR.W (A0)+ ;The subroutine is installed.
MOVE.W D0,(A0)+ ;Store the two arguments.
MOVE.W D1,(A0)+ ;Install the subroutine.
SUBQ.B #3,D7
BNE.S @4 ;If there is no PC range, indicate that fact.
MOVE.L Lo3Bytes,D4 ;Clear the high bytes of the two addresses.
AND.L D4,D2
AND.L D4,D3
CMP.L D2,D3
BCC.S @3 ;Make sure D2<=D3.
EXG D2,D3
@3 MOVE.L D2,(A0)+ ;Store the PC range.
MOVE.L D3,(A0)+
BRA.S A000OnOff
@4 ST (A0)
;This routine turns the A000 dispatcher on or off depending on the situation
A000OnOff
MOVE.W #A000Hook-A,_A000Hook-A(A2)
MOVE.B TrapRList,D0 ;The subroutine isn't installed.
BEQ.S @1
MOVE.B TrapSList,D0
BEQ.S @1
MOVE.B TrapDList,D0
BEQ.S @1
MOVE.B TrapCList,D0
BEQ.S @1
MOVE.B TrapIList,D0
BEQ.S @1
MOVE.B TrapGList,D0
BEQ.S @1
CLR.W _A000Hook-A(A2) ;Remove the subroutine.
@1 RTS
;############################
;## ##
;## A000 subhook section ##
;## ##
;############################
;
;The following are the subhooks for A000 trap intercepts.
;
;
;The following is for heap check, scramble and/or purge.
;
ScrambleHook
MOVEM.L D2-D7/A2-A6,-(SP)
SUB.W #$1E,D0 ;Is this a _NewPtr?
BEQ.S @22 ;YES.
SUBQ.W #$22-$1E,D0 ;NO. Is this a _NewHandle?
BEQ.S @22 ;YES.
SUBQ.W #$27-$22,D0 ;NO. Is this a _ReallocHandle?
BEQ.S @22 ;YES.
MOVEM.L 62(SP),D1/D2/A1 ;NO. Test for a _SetPtrSize or _SetHandleSize
ADDQ.W #$27-$20,D0
BEQ.S @21
SUBQ.W #$24-$20,D0
BNE.S @23 ;None of these. Don't do a heap scramble.
MOVE.L (A1),A1 ;De-reference the handle in a _SetHandleSize
@21 SUBQ.W #8,A1
MOVE.L (A1),D2 ;Get the size of the memory manager block.
AND.L Lo3Bytes,D2
SUBQ.L #8,D2 ;Subtract the size of the header.
MOVEQ #$0F,D3 ;Also subtract the correction value.
AND.B (A1),D3
SUB.L D3,D2
CMP.L D1,D2 ;Is the new size greater than the old size?
BGE.S @23 ;If not, don't scramble.
@22 BSR ScrambleHeap ;Call the ScrambleHeap routine.
BRA.S @24
@23 MOVEQ #0,D0 ;If not scrambled, return error code of zero.
@24 MOVEM.L (SP)+,D2-D7/A2-A6
RTS
;
;The following is for recording each trap.
;
RecordHook
MOVEM.L D2/A2,-(SP)
LEA RecordData+2,A1
TST.B (A1)+ ;If master switch is off, do nothing.
BMI.S @4
MOVE.B (A1)+,D2 ;Get the halting flag.
MOVE.W (A1)+,D1 ;Get the number of messages.
MOVE.L (A1),A2 ;Get the address of the table.
TST.B D2 ;Is halting enabled?
BEQ.S @1
MOVE #@6-A,D0 ;YES. If the table is about to overflow, exit.
CMP.W -6(A1),D1
BLS.S @5
@1 ADDQ.W #1,-6(A1) ;One more message is present.
ADDQ.W #6,A1
MOVE.W (A1),D2 ;Decrement the pointer to the current message
BNE.S @2 ;storing place.
MOVE.W D1,D2
@2 SUBQ.W #1,D2
MOVE.W D2,(A1)
ASL.W #4,D2 ;Copy the message.
ADD.W D2,A2
MOVE.W (A0),(A2)+ ;Copy the opcode.
MOVE.W Ticks+2,(A2)+ ;Copy the time.
MOVE.L A0,(A2)+ ;Copy its PC.
BTST #3,(A0)
BNE.S @3
MOVE.L $1A(SP),(A2)+ ;Also copy the values of D0 and A0.
MOVE.L $22(SP),(A2)
BRA.S @4
@3 MOVE.L $38(SP),(A2)+ ;Get the values of the top 8 stack bytes.
MOVE.L $3C(SP),(A2)+
;At this point the stack looks like this:
; D2 A2 Ret B D0 A0 Ret D0 D1 A0 A1 Ret A5 SR PC stk0 stk2
; 0000 0000 0000 00 0011 1111 1111 1111 1122 2222 2222 2222 2233 33 3333 3333 3333
; 0123 4567 89AB CD EF01 2345 6789 ABCD EF01 2345 6789 ABCD EF01 23 4567 89AB CDEF
@4 MOVEQ #0,D0 ;No errors.
@5 MOVEM.L (SP)+,D2/A2
RTS
@6 TRAPMon 'Record full'
;
;The following is for discipline.
;
DisciplineHook
;At this point the stack looks like this:
; Ret B D0 A0 Ret D0 D1 A0 A1 Ret A5 SR PC stack
; 0000 00 0000 1111 1111 1122 2222 2222 3333 3333 3344 44 4444 4455
; 0123 45 6789 0123 4567 8901 2345 6789 0123 4567 8901 23 4567 8901
MOVEM.L A2/A4/A6/D7,-(SP)
LEA 4*4+18(SP),A4 ;point A4 to the registers
LEA 4*4+48(SP),A6 ;point A6 to the stack
;At this point A6 points to the old stack and A4 points to this:
; D0 D1 A0 A1 Ret A5 SR PC
; 0000 0000 0011 1111 1111 2222 22 2222
; 0123 4567 8901 2345 6789 0123 45 6789
RegD0 EQU 0(A4)
RegD1 EQU 4(A4)
RegA0 EQU 8(A4)
RegA1 EQU 12(A4)
RegA5 EQU 20(A4)
RegSR EQU 24(A4)
RegPC EQU 26(A4)
Stack0 EQU 0(A6)
Stack2 EQU 2(A6)
Stack4 EQU 4(A6)
Stack6 EQU 6(A6)
Stack8 EQU 8(A6)
Stack10 EQU 10(A6)
Stack12 EQU 12(A6)
Stack14 EQU 14(A6)
Stack16 EQU 16(A6)
Stack18 EQU 18(A6)
Stack20 EQU 20(A6)
Stack22 EQU 22(A6)
Stack24 EQU 24(A6)
Stack26 EQU 26(A6)
Stack28 EQU 28(A6)
;The discipline code may trash D0, D1, A0, A1 and A2
MOVE.W (A0),D1 ;Get the actual trap word.
BTST #11,D1 ;Check what kind of trap.
BNE.S ToolboxTrap
OSTrap
LEA OSTraps,A0
AND.W #$FF,D1 ;Get the trap number.
BRA.S DisciplineTrap
ToolboxTrap
BTST #10,D1 ;Check if it is auto-pop.
BEQ.S @1
ADDQ #4,A6 ;Skip over auto-pop return address.
@1 LEA ToolTraps,A0
AND.W #$1FF,D1 ;Get the trap number.
DisciplineTrap
MOVEQ #0,D7
ADD.W D1,D1
MOVE.W 0(A0,D1.W),D1 ;Find the discipline code.
BEQ.S NoDiscipline
JSR 0(A0,D1.W) ;Call on discipline.
NoDiscipline
MOVE.W D7,D0 ;Return the error code.
MOVEM.L (SP)+,A2/A4/A6/D7
RTS
;
;The following is for checksumming on each trap.
;
ChecksumHook
MOVE.L D2,-(SP)
MOVEQ #0,D2 ;Calculate the checksum.
MOVEM.L ChecksumValue+2,D0/D1
BSR Checker
MOVEQ #0,D0
CMP.W ChecksumValue,D2 ;If the checksum matches, no error.
BEQ.S @1
MOVE #@2-A,D0 ;Otherwise report the checksum error.
@1 MOVE.L (SP)+,D2
RTS
@2 TRAPMon 'Checksum failed'
;
;The following is for trap intercept.
;
InterceptHook
MOVE #@1-A,D0 ;Always cause an error.
RTS
@1 TRAPMon 'Trap intercepted'
;
;The following is for trap signalling.
;
SignalHook
MOVEQ #0,D0
MOVE.B UserInform,D1 ;Cause an error if UserInform is nonzero.
BEQ.S @1
MOVE #@2-A,D0
@1 RTS
@2 TRAPMon 'Trap signal'
;#########################################
;## ##
;## Heap check/scramble/purge section ##
;## ##
;#########################################
;+-----------------------------------------+
;| Check, scramble, and/or purge the Heap. |
;+-----------------------------------------+
;|
;|ENTRY: ScrambleHeap
;|
;|OUT: D0.L' Zero if scramble successful; HeapError-A otherwise.
;|
;|Destroys D1-D7,A0-A6.
;|
ScrambleHeap
MOVE.L SP,A2
MOVE.B CurrentHeap,D0
BSR GetZone ;Get the requested heap zone.
BNE ScrambleError
MOVE.B PurgeAlso,D0
BEQ.S @1
BSR.S PurgeHeap
@1 LEA 48(A6),A3
CLR.L (A3)+
ScrambleLoop
MOVEQ #0,D0 ;(Give a return code of 0 if exiting.)
CMP.L (A6),A3 ;Exit if done.
BEQ ScrambleEnd
BSR GetBlockInfo ;Get information about the first block.
BMI.S ScrambleLoop ;If it can't be moved, fetch the next block.
MOVE.B CheckOnly,D2 ;If it isn't supposed to be moved, also fetch the
BPL.S ScrambleLoop ;next block.
MOVE.B D0,D3 ;Save the information about the first block.
MOVE.L D1,D4
MOVE.L A4,A5 ;A3 is the current address.
CMP.L (A6),A3 ;D3 is the type of the first block.
BEQ.S ScrambleClr ;D4 is the length of the first block.
BSR GetBlockInfo ;A5 is the address of the first block.
BMI.S ScrambleClr ;D0 is the type of the second block.
ADD.B D3,D0 ;D1 is the length of the second block.
BEQ.S Scramble2Blank ;A4 is the address of the second block.
BMI ScrambleSwap
TST.B D3
BEQ.S ScrambleAlter2nd
MOVEQ #0,D6
BSR.S AlterCount ;Get all the free areas after the block.
BSR.S AlterLen ;Find their total length.
BSR.S Alter1st ;Swap a block with a free area. The block is first.
EXG D1,D4
MOVE.L A5,A0
MOVE.L A3,A1
MOVE.L D1,D0
_BlockMove
ScrambleClr2
MOVEQ #4,D1 ;Don't touch the next block.
BSR.S ScrambleClear
BRA.S ScrambleLoop
ScrambleAlter2nd
BSR.S Alter2nd ;Swap a free area with a block. The block is
MOVE.L A4,A0 ;second.
MOVE.L A5,A1
MOVE.L D1,D0
MOVE.L D0,D5
_BlockMove
MOVE.L D4,(A3) ;Store the length of the free area.
BRA.S ScrambleLoop
Scramble2Blank
MOVE.L A4,A3 ;Skip past one blank block.
ScrambleClr
TST.B D3 ;Check if the first block is a free area.
BNE.S ScrambleLoop ;If not, don't clear it.
CMP.B #$C1,D0 ;In the special case that the first block is a free
BNE.S ScrambleClr2 ;block and the second one an immovable free block,
MOVE.L D1,-(SP) ;consolidate the two blocks.
MOVEQ #0,D1 ;Erase the first long word of the second free block
BSR.S ScrambleClear ;as well.
MOVE.L (SP)+,D1
ADD.L D1,-(A5)
BRA.S ScrambleLoop
PurgeHeap
MOVE.L theZone,-(SP) ;Call MaxMem to do a purge.
MOVE.L A6,theZone
_MaxMem
MOVE.L (SP)+,theZone
RTS
Alter1st
MOVE.L 4(A5),A0 ;Adjust the handle to the first block.
ADD.L D1,0(A6,A0.L)
RTS
AlterCount
MOVEQ #0,D7 ;On exit, D7 will contain the number of blocks that
MOVE.L A4,A1 ;were found.
@1 ADDQ.W #1,D7
CMP.L (A6),A3 ;Don't go past the end of the Heap.
BEQ.S @2
BSR GetBlockInfo ;Get a block.
CMP.B D0,D6 ;Does it have the desired type?
BEQ.S @1 ;YES. Look at the next block.
MOVE.L A4,A3 ;NO. Go to the previous block.
@2 MOVE.L A1,A4 ;Restore A4. A3 contains one byte past the end of
RTS ;the last block found.
Alter2nd
MOVEQ #$40,D6 ;Skip past any following relocatable blocks.
BSR.S AlterCount
MOVE.L A1,A3 ;Do a second pass over these blocks.
@1 BSR GetBlockInfo
SUB.L D4,(A0) ;Adjust the handles of all these blocks.
SUBQ.W #1,D7
BNE.S @1
MOVE.L A1,A4
AlterLen
MOVE.L A3,D1 ;Find the total length of the blocks that were
SUB.L A4,D1 ;found.
SUBA.L D4,A3 ;ScrambleLoop will fetch the second block.
RTS
ScrambleClear
MOVE.L D4,(A5)+ ;Clear the first block. (Assumes that it is a free
SUB.L D1,D4 ;area).
ADD.L D4,A5
MOVE.L #'XYXY',D0
LSR.L #1,D4 ;D4 is the number of words to clear.
MOVE.L D4,D1
AND.W #31,D1 ;Use a slower loop to clear a number of words that
BRA.S @2 ;is not a multiple of 32 words.
@1 MOVE.W D0,-(A5)
@2 DBRA D1,@1
LSR.L #5,D4
BEQ.S @5
MOVE.L D0,D1 ;Now use a super-fast loop to clear the rest in
MOVE.L D0,D2 ;multiples of 32 words.
MOVE.L D0,D3
MOVE.L D0,D7
MOVE.L D0,A0
MOVE.L D0,A1
MOVE.L D0,A4
BRA.S @4
@3 MOVEM.L D0/D1/D2/D3/D7/A0/A1/A4,-(A5)
MOVEM.L D0/D1/D2/D3/D7/A0/A1/A4,-(A5)
@4 DBRA D4,@3
@5 RTS
ScrambleSwap
BSR.S Alter2nd ;Swap two blocks. This may not be a very fast
BSR.S Alter1st ;operation.
MOVE.L #160*5,D2
CMP.L D2,D1 ;If both blocks are large, use the slow algorithm.
BLS.S @1
CMP.L D2,D4
BHI.S SlowSwap
@1 MOVE.W #160,D2 ;Use a lightning-fast algorithm if at least one
SUB.L D2,SP ;block is small enough. Reserve 160 bytes on stack.
ADD.L D1,A4 ;A4 now points to the end of the second block.
CMP.L D1,D4
BHI.S @10
ADD.L D4,D1 ;D1 now contains the total length.
@2 MOVE.L D2,D0 ;The first block is the smaller one.
SUB.L D2,D4
BCC.S @3 ;Put either 160 or the remaining length of the first
ADD.L D2,D4 ;block into D0, whichever is smaller.
MOVE.L D4,D0
MOVEQ #0,D4
@3 MOVE.L A5,A0 ;Save D0 bytes from the beginning of the first
MOVE.L SP,A1 ;block.
BSR.S FastPush
MOVE.L A5,A1 ;Shift the remaining bytes to lower memory to cover
NEG.L D0 ;the hole that was created.
ADD.L D1,D0
_BlockMove
MOVE.L SP,A0 ;Store the saved bytes at the end of the second
MOVE.L A4,A1 ;block.
SUB.W D3,A1
BSR.S FastPull
TST.L D4
BNE.S @2 ;If the swap isn't complete, shift again.
BRA.S @20
@10 ADD.L D1,D4 ;D4 now contains the total length.
@11 MOVE.L D2,D0
SUB.L D2,D1
BCC.S @12 ;Put either 160 or the remaining length of the
ADD.L D2,D1 ;second block into D0, whichever is smaller.
MOVE.L D1,D0
MOVEQ #0,D1
@12 MOVE.L A4,A0 ;Save D0 bytes from the end of the second block.
SUB.W D0,A0
MOVE.L SP,A1
BSR.S FastPush
MOVE.L A5,A0 ;Shift the remaining bytes to higher memory to cover
MOVE.L A5,A1 ;the hole that was created.
ADD.W D0,A1
NEG.L D0
ADD.L D4,D0
_BlockMove
MOVE.L SP,A0 ;Store the saved bytes at the beginning of the
MOVE.L A5,A1 ;first block.
BSR.S FastPull
TST.L D1
BNE.S @11 ;If the swap isn't complete, shift again.
@20 ADD.L D2,SP ;Release the memory reserved on the stack and exit.
toScrambleLoop BRA ScrambleLoop
FastPush
MOVE.W D0,D3
FastPull
LSR.W #2,D3 ;This is a semi-efficient block move routine that
BCC.S @2 ;doesn't have the overhead of calling _BlockMove.
MOVE.W (A0)+,(A1)+
BRA.S @2
@1 MOVE.L (A0)+,(A1)+
@2 DBRA D3,@1
MOVE.W D0,D3
RTS
SlowSwap
BSR.S SlowScramble ;Call the subroutine and go back to the main loop.
BRA.S toScrambleLoop
SlowScramble
MOVE.L A4,A0 ;This is a slower algorithm used for larger blocks.
ADD.L D1,A0 ;A0 is one byte beyond the last byte to be moved.
ADD.L D4,D1
MOVE.L D1,D7 ;D7 is now the total length.
LSR.L #1,D1 ;D1 is now the total length/2.
BRA.S @4
@5 ADD.L D7,A1 ;In this loop, continue to swap the word in the
CMP.L A0,A1 ;register with the next word in the memory until
BNE.S @2 ;the two blocks are transposed. Do not swap any
MOVE.W D2,(A1) ;of the words more than once; if that is about to
@4 MOVE.W -(A0),D2 ;happen, move the pointer to the preceeding word.
MOVE.L A0,A1
BRA.S @3
@1 SUB.L D4,A1
CMP.L A5,A1
BLT.S @5
@2 MOVE.W (A1),D3
MOVE.W D2,(A1)
MOVE.W D3,D2
@3 DBRA D1,@1
SUB.L val10000,D1
BCC.S @1
RTS
;+--------------------------+
;| Get either the system or |
;| application heap zone. |
;| Avoid address errors. |
;+--------------------------+
;|
;|ENTRY: GetZone
;|
;|IN: Z: flag set for system zone, clear for application zone.
;|
;|OUT: D0.L' ^heap zone.
;| A6' ^heap zone (same as D0.L').
;|
;|Destroys A3.
;|
GetZone BNE.S @1 ;Get the requested heap zone and put it into D0 and
LEA SysZone,A3 ;A6, relying on the zero flag on entry:
BRA.S @2 ;Z set for system zone, clear for application zone.
@1 LEA ApplZone,A3
@2 MOVE.L (A3),D0
BCLR #0,D0 ;If the address is odd, make it even.
MOVEA.L D0,A6
RTS
;+------------------------------------------------+
;| Examine one heap block. If an error is found, |
;| MOVE.L A2,SP, MOVE #HeapError-A,D0, and RTS |
;| are executed. |
;+------------------------------------------------+
;|
;|ENTRY: GetBlockInfo
;|
;|IN: A3: ^block's header.
;| A6: ^heap zone that contains the block.
;| A2: SP to use in case an error is found.
;|
;|OUT: If an error was found, the error routine is entered. Otherwise,
;| A3' ^next block's header.
;| A4' A3:
;| D1.L' length of this block.
;| CCR' represents TST.B D0'.
;| D0.B' block type ($00,$40,$80,$C0,$C1).
;| =$00' free block.
;| =$40' relocatable block.
;| D2.L' handle value.
;| A0' handle address.
;| =$80' non-relocatable block.
;| =$C0' locked relocatable block.
;| =$C1 a free block that shouldn't be moved.
;|
;|Destroys A0.
;|
GetBlockInfo
MOVE.L A3,A4 ;Save A3.
MOVE.B (A3),D0 ;Get the block type.
MOVE.L (A3)+,D1 ;Get the block length.
MOVE.L (A3)+,A0 ;Get the handle or heap zone address.
AND.L Lo3Bytes,D1
AND.B #$C0,D0
BEQ.S InfoEnd ;If this is a free block, leave.
BMI.S InfoRelocatable ;Do relocatable and illegal blocks.
MOVEQ #$FFFFFF80,D0 ;This is a nonrelocatable block. The indicated heap
CMP.L A0,A6 ;zone address should match A6.
BEQ.S InfoEnd
ScrambleError
MOVE.L A2,SP ;Go to the error routine.
MOVE #HeapError-A,D0
RTS
HeapError TRAPMon 'Heap error'
InfoRelocatable
SUB.B #$40,D0 ;If this is a $C0 type block, it is illegal.
BMI.S ScrambleError
MOVE.L A0,D2 ;If the handle address is odd, the block is illegal.
LSR.B #1,D2
BCS.S ScrambleError
ADD.L A6,A0
MOVE.L (A0),D2 ;If this relocatable block is locked, give it the
BPL.S @1 ;$C0 type.
MOVEQ #$FFFFFFC0,D0
@1 AND.L Lo3Bytes,D2
CMP.L D2,A3 ;Make sure that this block's handle points back to
BNE.S ScrambleError ;the block.
InfoEnd SUBQ.L #8,D1 ;Now add the length of the block to the address.
BCS.S ScrambleError ;If the block size is less than eight, give an
BTST #0,D1 ;error.
BNE.S ScrambleError
ADD.L D1,A3
CMP.L (A6),A3
BCS.S @1
BHI.S ScrambleError ;Don't allow blocks beyond the end of the Heap.
TST.B D0 ;If the last block is a free area, don't scramble it.
BNE.S @1
MOVEQ #$FFFFFFC1,D0
@1 ADDQ.L #8,D1 ;Correct for the two autoincrement instructions.
TST.B D0
ScrambleEnd
RTS
;######################
;## ##
;## Label routines ##
;## ##
;######################
;+--------------------------------------------------------+
;| Check if D2 is in a 'CODE' resource, and, if so, |
;| attempt to find the name of the routine containing D2. |
;+--------------------------------------------------------+
;|
;|ENTRY: CodeLabelScan
;|
;|IN: D2.L: address to identify.
;| D0.L: 0.
;| D5.L: if D2 is in a resource, offset from the resource beginning to D2.
;| D6.L: if D2 is in a resource, the resource type; otherwise, 0.
;| D7.L: Bits 0..15 contain the resource ID. Bits 16..23 contain the value of _Inhibits.
;| A4: if D2 is in a resource, beginning address of the heap block. (D2:-D5:)
;| A3: if D2 is in a resource, ending address of the heap block. (D2:-D5:)
;| A5: ^Monitor's variables.
;|(D4 is initialized by the Monitor, but this routine does not use it.)
;|
;|OUT: D0.L'=0 D2 could not be identified.
;| D2.L' D2.L:.
;| D0.L'<>0 D2 was identified.
;| D0.L' first four letters of name.
;| D1.L' last four letters of name.
;| A1' address of the routine's beginning (the LINK instruction).
;| D2.L' D2.L:-A1'.
;|
;|Destroys D1,D3,A0,A1.
;|
CodeLabelScan
MOVEM.L D4/D6/D7,-(SP) ;Save registers.
CMP.L #'CODE',D6 ;Don't search for code routine names unless this is
BNE.S @10 ;a code segment.
MOVE.L D2,D7 ;D7 will contain D2 truncated to an even value.
BCLR #0,D7
MOVE.L D7,A0
MOVE.L A3,D3 ;D3 contains the number of words left to scan
SUB.L D7,D3 ;before giving up at $800 or finishing at the end of
CMP.W #$800,D3 ;the block.
BCS.S @1
MOVE.W #$800,D3
@1 LSR.W #1,D3
ADDQ.L #2,D7 ;Increment the starting position pointer by 2.
@19 MOVE.W #$4E75,D1 ;D1.W: RTS
MOVE.W #$4ED0,D6 ;D6.W: JMP (A0)
MOVE.W #$4E56,D4 ;D4.W: LINK A6,#____
BRA.S @3
@2 MOVE.W (A0)+,D0 ;Get the next word.
CMP.W D1,D0 ;Search for one of the above instructions.
BEQ.S @20 ;If RTS or JMP (A0) is found, investigate further.
CMP.W D6,D0
BEQ.S @20
CMP.W D4,D0
@3 DBEQ D3,@2 ;If the LINK is found first, exit with no label.
BNE.S @10 ;If the LINK is the first instruction encountered,
CMPA.L D7,A0 ;leave it as it is because it may be the beginning
BEQ.S @19 ;of the subroutine.
@10 MOVEQ #0,D0 ;Pass back no label code.
@11 MOVEM.L (SP)+,D4/D6/D7 ;Return.
RTS
@20 CMP.W #4,D3 ;If there are less than eight bytes left to scan,
BCS.S @10 ;it's not possible to have a full name here.
BSR.S CheckUNLK ;Check for an UNLK instruction before the RTS or
BNE.S @3 ;JMP (A0). If not found, continue searching.
MOVEQ #7,D6
@21 ROL.L #8,D0 ;Check the name to make sure that there are eight
ROL.L #8,D1 ;letters of valid ASCII values present.
MOVE.B D1,D0
MOVE.B (A0)+,D1
CMP.B #6,D6
BCS.S @22
AND.B #$7F,D1 ;Clear the high bit of the first and second bytes.
@22 CMP.B #' ',D1 ;Anything between $20 and $7E is valid.
BCS.S @10
CMP.B #$7F,D1
BCC.S @10
DBRA D6,@21
MOVE.W D5,D3 ;A valid name has been found. Now search backwards
LSR.W #1,D3 ;for the LINK instruction.
MOVE.L D7,A1
@23 CMP.W -(A1),D4
DBEQ D3,@23
BNE.S @10 ;If run out of the block, exit.
SUB.L A1,D2 ;Otherwise give the offset in D2 and return
BRA.S @11 ;successfully.
;+-------------------------------------------------------+
;| Make sure that an UNLK A6 instruction exists no more |
;| than ten words in front of A0. Also make sure that |
;| there is no LINK A6 between the UNLK A6 and A0. |
;+-------------------------------------------------------+
;|
;|ENTRY: CheckUNLK
;|
;|IN: A0: Address from which to search.
;|
;|OUT: Z flag' set if the conditions above satisfied, clear otherwise.
;|
;|Destroys nothing.
;|
CheckUNLK MOVEM.L D0/A0,-(SP) ;Save registers.
MOVEQ #9,D0 ;Search ten words.
@1 CMP.W #$4E5E,-(A0) ;UNLK A6
BEQ.S @2
CMP.W #$4E56,(A0) ;LINK A6,#____
DBEQ D0,@1
MOVEQ #-1,D0 ;If not found or LINK found first, clear Z flag.
@2 MOVEM.L (SP)+,D0/A0 ;Return (MOVEM preserves flags).
RTS
;+----------------------------------+
;| Find a given embedded routine |
;| 8-character name in code blocks. |
;| See manual for details. |
;+----------------------------------+
;|
;|ENTRY: CodeLabelFind
;|
;|IN: D0.L: first four characters of the name converted to upper case.
;| D1.L: last four characters of the name converted to upper case.
;| D7.L: bits 16..23 contain the value of _Inhibits.
;| A5: ^Monitor's variables.
;|
;|OUT: D0.L'=0 the name has been found.
;| D2.L' the location of the routine that has the given name.
;| D0.L'=D0.L: the name has not been found.
;|
;|Destroys D2,D3,A0,A1.
;|
CodeLabelFind
MOVEM.L D0/D1/D4-D7/A2-A4/A6,-(SP)
BTST #16+3,D7 ;If can't scan resources, do nothing.
BNE @40
MOVE.L SP,A6
MOVE.L $A50,D1 ;Start with the first resource file.
@1 JSR _NextCResFile ;Check the next file.
BEQ @40 ;If there is none, no data will be found.
MOVE.L A1,A0
MOVE.W (A0)+,D3 ;D3 has the number of types+1.
MOVE.L #'CODE',D2
@11 CMP.L (A0)+,D2
ADDQ.W #4,A0 ;Look for blocks of type 'CODE'.
DBEQ D3,@11
BNE.S @1 ;If not found, scan the next file.
MOVE.W -(A0),D0
ADD.W D0,A1 ;Find the ID list and check for address errors.
LSR.W #1,D0
BCS.S @1
MOVE.W -(A0),D6 ;D6 now has the number of 'CODE' IDs in the table.
@12 ADDQ.W #8,A1
MOVE.L (A1)+,A0 ;See if this 'CODE' segment is legally in memory.
BSR IndirectA0
BCS.S @50 ;NO.
TST.W -12(A1) ;YES. If its ID is zero, however, do not scan it.
BEQ.S @50
MOVE.L -8(A0),D0
AND.L Lo3Bytes,D0
MOVEQ #$0F,D2
AND.B -8(A0),D2 ;Subtract the size correction from the size.
SUB.L D2,D0
MOVEQ #8,D2
SUB.L D2,D0
BMI.S @50 ;If a negative number results, skip to the next
LSR.L #1,D0 ;block.
CMP.L #$8000,D0
BCS.S @13
MOVE.L #$7FFF,D0
@13 MOVE.W #$4E56,D2 ;D2.W: LINK A6,#____
MOVE.W #$4E75,D3 ;D3.W: RTS
MOVE.W #$4ED0,D4 ;D4.W: JMP (A0)
BRA.S @21
@20 CMP.W (A0)+,D2 ;Search for a LINK instruction.
@21 DBEQ D0,@20
BNE.S @50 ;Not found within the block.
@22 MOVEA.L A0,A2 ;Save the address and look for either RTS or
BRA.S @24 ;JMP (A0).
@23 MOVE.W (A0)+,D5
CMP.W D5,D3
BEQ.S @30
CMP.W D5,D4
BEQ.S @30
CMP.W D5,D2 ;If another LINK is found first, restart this loop.
@24 DBEQ D0,@23
BNE.S @50
MOVEQ #-1,D5 ;Clear the Z flag and search again.
BRA.S @22
@30 BSR CheckUNLK ;Check for an UNLK instruction before the RTS or
BNE.S @24 ;JMP (A0).
BSR.S CheckName
BNE.S @21
SUBQ.W #2,A2
MOVE.L A2,D2
CLR.L (SP) ;Clear D0 on the stack image.
@40 MOVEM.L (SP)+,D0/D1/D4-D7/A2-A4/A6
RTS
@50 DBRA D6,@12 ;Examine the next block, or, if there are no more,
BRA @1 ;the next file.
;+---------------------------------------------------------------------------------+
;| Compare the names at (A0)+ and (A6)+. Convert the name at (A0)+ to upper case |
;| and clear the 7th bit in its first 2 characters for the purpose of comparison. |
;| The name at (A6)+ is assumed to be in upper case, as it will be if it was |
;| generated by the Monitor. Both names must be eight characters long. |
;+---------------------------------------------------------------------------------+
;|
;|ENTRY: CheckName
;|
;|IN: A0: string1, upper or lower case, 7th bit clear or set on first character.
;| A6: string2, upper case only, 7th bit clear.
;|
;|OUT: Z flag' set if uppercase(string1)=string2
;| clear otherwise.
;|
;|Destroys nothing.
;|
CheckName
MOVEM.L D0/D1/A1/A2,-(SP)
MOVEQ #7,D0 ;Compare eight characters.
MOVE.L A6,A1 ;Use copies of A0 and A6.
MOVE.L A0,A2
@4 MOVEQ #$7F,D1 ;Clear the high bit of the first character.
AND.B (A2)+,D1
BRA.S @3
@1 CMP.B #6,D0
BHS.S @4
MOVE.B (A2)+,D1
@3 CMP.B #'a',D1 ;Convert to upper case.
BCS.S @2
CMP.B #'z'+1,D1
BCC.S @2
SUB.B #$20,D1
@2 CMP.B (A1)+,D1 ;Compare and exit as soon as a mismatch is found or
DBNE D0,@1 ;eight characters match.
MOVEM.L (SP)+,D0/D1/A1/A2
RTS
;+---------------------------+
;| Find a given 8-character |
;| label in the label table. |
;| See manual for details. |
;+---------------------------+
;|
;|ENTRY: LabelFind
;|
;|IN: D0.L: first four characters of the name converted to upper case.
;| D1.L: last four characters of the name converted to upper case.
;| D7: bits 16..23 contain the value of _Inhibits.
;| A5: ^Monitor's variables.
;|
;|OUT: D0.L'=0 the name has been found.
;| D2.L' the location of the routine that has the given name.
;| D0.L'=D0.L: the name has not been found.
;| D2.L' unpredictable.
;|
;|Destroys D3,A0,A1.
;|
;|
;|ENTRY: LabelFind.
;|
;|Same as LabelFind except that if D2.B is nonzero, the subroutine will not check if the resource is in
;|memory for resource-relative labels. Moreover, the address of the label will be passed back in
;|A0 if the label is found. However the address of built-in labels is never returned.
;|
LabelFind
MOVEQ #0,D2
LabelFind.
MOVE.B LabelEnabled,D3 ;If there is no table of labels, do nothing.
MOVEM.L D0/D1/D5/D6/A3/A4/A6,-(SP)
MOVE.L SP,A6 ;A6 points to the saved name on the stack.
BMI.S @20
MOVE.L LabelTable,A0
SUBQ.W #8,A0
MOVE.W NumLabels,D3
MOVEQ #-1,D0 ;Clear the Z flag.
BRA.S @2
@1 ADD.W #16,A0 ;Check the names in the label table.
BSR.S CheckName
@2 DBEQ D3,@1
BEQ.S @21 ;If found, continue
@20 LEA UALabelTable+8,A0 ;Point to built in label table.
MOVE.W #NumUALabels,D3
MOVEQ #-1,D0
BRA.S @22
@23 ADD.W #16,A0
BSR.S CheckName
@22 DBEQ D3,@23
@21 BNE.S @10 ;If no match, exit.
MOVE.L -(A0),D3 ;Determine whether this is an absolute or
MOVE.B D2,D0 ;resource-relative label.
MOVE.L -(A0),D2
TST.B (A0)
BEQ.S @3 ;If absolute, exit successfully.
TST.B D0
BNE.S @3 ;If supposed to pass back label address, exit now.
BTST #16+3,D7 ;If resource-relative, resource scanning must not be
BNE.S @10 ;inhibited!
SWAP D3
JSR _FindRes ;Find the desired resource, and, if all is well,
TST.B D0 ;add the offset to its beginning.
BNE.S @10
CLR.W D3
SWAP D3
ADD.L D3,D2
@3
LEA UALabelTable,A1
CMP.L A1,A0
BLO.S @24
LEA UALabelTableEnd,A1
CMP.L A1,A0
BHS.S @24
MOVEQ #0,D0
MOVE.L D0,A0 ;Do NOT return a pointer for built-ins
@24 CLR.L (SP) ;Clear D0 on the stack image.
@10 MOVEM.L (SP)+,D0/D1/D5/D6/A3/A4/A6
@11 RTS
;+------------------------------------+
;| Search the label table for a label |
;| that could be used to identify D2. |
;| The resource-relative labels will |
;| be ignored if D6 is 0. |
;+------------------------------------+
;|
;|ENTRY: LabelScan
;|
;|IN: D2.L: address to identify.
;| D0.L: 0.
;| D5.L: if D2 is in a resource, offset from the resource beginning to D2.
;| D6.L: if D2 is in a resource, the resource type; otherwise, 0.
;| D7.L: Bits 0..15 contain the resource ID. Bits 16..23 contain the value of _Inhibits.
;| A4: if D2 is in a resource, beginning address of the heap block. (D2:-D5:)
;| A3: if D2 is in a resource, ending address of the heap block. (D2:-D5:)
;| A5: ^Monitor's variables.
;|(D4 is initialized by the Monitor, but this routine does not use it.)
;|
;|OUT: D0.L'=0 D2 could not be identified.
;| D2.L' D2.L:.
;| D0.L'<>0 D2 was identified.
;| D0.L' first four letters of name.
;| D1.L' last four letters of name.
;| D2.L' offset from the label to D2.L.
;|
;|Destroys D1,D3,A0,A1.
;|
LabelScan
MOVE.B LabelEnabled,D3 ;If there is no table of labels, do nothing.
MOVEM.L D4/D5,-(SP) ;Save registers.
BMI.S @20
MOVE.L LabelTable,A0
MOVE.W NumLabels,D3
MOVEQ #-1,D5 ;Assume that the best fit was 4294967295 bytes off.
BRA.S @10
@1 MOVE.L A0,A1 ;Which type of a label is this?
TST.B (A1)
BEQ.S @2
CMP.L (A1)+,D6 ;Resource-type. The resource type and ID must
BNE.S @5 ;match exactly.
CMP.W (A1)+,D7
BNE.S @5
MOVEQ #0,D4 ;Get the address pointed by this label into D4.
MOVE.W (A1)+,D4
ADD.L A4,D4
BRA.S @3
@2 MOVE.L (A1)+,D4 ;Absolute-type. The given location must be below
CMP.L (A1)+,D2 ;the maximum address given. If it is, get the
BCC.S @5 ;address pointed by this label into D4.
@3 SUB.L D4,D2
BCS.S @4 ;Calculate the difference between D4 and the
CMP.L D5,D2 ;location given, and check if this is a closest
BCC.S @4 ;match.
MOVE.L D2,D5
MOVE.L (A1)+,D0 ;If so, copy the name into D0 and D1 and the
MOVE.L (A1),D1 ;difference into D5.
@4 ADD.L D4,D2
@5 ADD.W #16,A0
@10 DBRA D3,@1
LEA UALabelTableEnd,A1 ;Check if we were scanning the built in table.
CMP.L A0,A1
BEQ.S @21 ;If so, we are done
@20 LEA UALabelTable,A0
MOVE.W #NumUALabels,D3
BRA.S @10
@21 TST.L D0 ;If a good label has been found, put the difference
BEQ.S @11 ;into D2.
MOVE.L D5,D2
@11 MOVEM.L (SP)+,D4/D5 ;Restore registers.
@12 RTS
;####################################
;## ##
;## Heap identification routines ##
;## ##
;####################################
STRING_FORMAT 2 ;Precede strings with length byte.
Heap.V1
DC GrayRgn ;Locations of some low memory locations that
DC MenuList ;contain handles.
DC TEScrpHandle ;To add more, instert additional addresses here and
DC ScrapHandle ;put their names into Heap.L1.
DC SaveVisRgn
Heap.V1End
Heap.V2
DC.B visRgn,clipRgn,picSave,rgnSave,polySave
DC.B structRgn,contRgn,updateRgn
DC.B wDataHandle,wTitleHandle,windowPic
DC.B items,teHandle ;Only in dialog windows.
Heap.FInfo DC.B 'FinderInfo'
Heap.Control DC.B 'Control'
Heap.DI DC.B 'Item #$'
Heap.DI2 DC.B ' Type $'
Heap.W2 DC.B '(Window @$'
Heap.ParamText DC.B 'ParamText'
Heap.Window DC.B 'Window #$'
Heap.Kind DC.B ', Kind $'
Heap.Map DC.B 'Resource map $'
Heap.WMgrPort DC.B 'WMgrPort'
Heap.RPSpace DC.B ') '
Heap.RP8Spaces DC.B ') '
Heap..
Heap.L1
DC.B 'GrayRgn' ;See Heap.V1 on how to add more names here.
DC.B 'MenuList'
DC.B 'TEScrap'
DC.B 'Scrap'
DC.B 'SaveVisRgn'
Heap.L2
DC.B 'VisRgn','ClipRgn','PicSave','RgnSave','PolySave'
DC.B 'StructRgn','ContRgn','UpdateRgn'
DC.B 'WData','WTitle','WPic'
DC.B 'Items','TEHandle'
.ALIGN 2
STRING_FORMAT 0 ;Normal strings
;+--------------------------------+
;| Identify the heap block at A3. |
;+--------------------------------+
;|
;|ENTRY: HeapIdentify
;|
;|IN: D3.W: 0 if nonrelocatable block, 1 if relocatable block, 2 if resource relocatable block.
;| A1: ^heap zone containing the block.
;| A2: ^text area for the information about the block.
;| A3: ^block.
;| A4: another pointer into the text area. See the manual.
;| A5: ^Monitor's variables.
;| A6: ^handle if this is a relocatable block.
;|
;|OUT: A2' A2: moved past the text stored.
;|
;|Destroys D0-D7,A0,A1,A3,A4,A6.
;|
HeapIdentify
SUBQ.W #1,D3 ;Look only at unidentified relocatable blocks and
BEQ.S Heap.Relocatable ;nonrelocatable blocks.
BCC.S Heap.RTS
MOVEQ #18,D1 ;This is a nonrelocatable block. Print 19 spaces.
MOVEQ #' ',D0
@1 MOVE.B D0,(A2)+
DBRA D1,@1
CMP.L WMgrPort,A3 ;Is this the Window Manager
BNE.S @2 ;port?
MOVEQ #Heap.WMgrPort-Heap..,D7
BRA.S Heap.PString
@2 LEA WindowList-nextWindow,A0;Scan the window list to check if this block is in
MOVEQ #-1,D0 ;it.
@3 MOVE.L nextWindow(A0),A0
ADDQ.B #1,D0
BSR CheckA0
BCS.S Heap.RTS ;The list is over; quit.
CMP.L A0,A3
BNE.S @3
MOVEQ #Heap.Window-Heap..,D7 ;This block is in the list.
BSR.S Heap.PString
JSR _Put2Dig ;Display both the window number and kind.
MOVEQ #Heap.Kind-Heap..,D7
MOVE.W windowKind(A0),D0
Heap.S.D BSR.S Heap.PString ;Print a string and then a number.
JMP _Put4Dig
;+----------------------------------------------------+
;| Transfer a string from the string list onto (A2)+. |
;+----------------------------------------------------+
;|
;|ENTRY: Heap.IString
;|
;|IN: A2: ^destination text.
;| D1.W: string number (0=first, 1=second, etc.)
;| D7.W: offset to the first string from Heap..
;|
;|OUT: A2' A2: moved past the copied string.
;|
;|Destroys D1,D7.
;|
;|ENTRY: Heap.PString
;|
;|Same as above, except that D1.W: is set to zero.
;|
Heap.PString MOVEQ #0,D1 ;Get the first string encountered in list.
Heap.IString MOVE.L A0,-(SP) ;Get the D1th string after the one at Heap..+D7.
LEA Heap..,A0 ;A0 was saved.
ADD.W D7,A0
MOVEQ #0,D7
BRA.S @1
@2 ADD.W D7,A0
@1 MOVE.B (A0)+,D7 ;Get the length of a string.
DBRA D1,@2 ;If indexing, skip past that string.
BRA.S @3
@4 MOVE.B (A0)+,(A2)+ ;Copy the string into the destination.
@3 DBRA D7,@4
MOVE.L (SP)+,A0 ;Restore A0 and exit.
Heap.RTS RTS
Heap.Relocatable
MOVE.W #' ',(A2)+ ;Print two spaces.
MOVE.L CurrentA5,A0
BSR.S @49 ;Check if this block is the Finder information
BCS.S @1 ;handle.
MOVEQ #Heap.FInfo-Heap..,D7
CMP.L 16(A0),A6
BEQ.S Heap.PString ;Yes. Print the appriopriate information.
@1 MOVEQ #(Heap.V1End-Heap.V1)/2-1,D1
LEA Heap.V1End,A0
MOVEQ #0,D7 ;Check if the low memory locations have
@2 MOVE.W -(A0),A4 ;handles to this block.
CMP.L (A4),A6
BEQ.S Heap.IString
DBRA D1,@2
MOVEQ #'0',D2 ;Check the four ParamText locations.
LEA DAStrings,A0
@3 CMP.L (A0)+,A6
BNE.S @4
MOVEQ #Heap.ParamText-Heap..,D7
BSR.S Heap.PString
MOVE.B D2,(A2)+
@9 RTS
@4 ADDQ.B #1,D2
CMP.B #'4',D2
BNE.S @3
LEA TopMapHndl-nextMap,A0 ;Scan the resource file list.
@10 MOVE.L nextMap(A0),A0
BSR IndirectA0 ;If there is a problem indirecting, abandon scan.
BCS.S @11
CMP.L A0,A3 ;Is this the desired block?
BNE.S @10 ;NO. Scan more.
MOVEQ #Heap.Map-Heap..,D7 ;YES. Give information.
MOVE.W resFileID(A0),D0
BRA Heap.S.D ;Exit.
@49 BRA CheckA0
@30 BSR Heap.WString ;Print the type of handle found.
MOVEQ #Heap.L2-Heap..,D7
BRA Heap.IString
@11 MOVEQ #0,D3
MOVE.L WMgrPort,A0
BRA.S @50
@51 NOT.B D3 ;Switch from scanning WMgrPort to the window list.
BEQ.S @9
LEA WindowList-nextWindow,A4;Scan the window list.
@12 MOVE.L nextWindow(A4),A0
@50 BSR.S @49
BCS.S @51 ;The list is over; quit.
MOVE.L A0,A4 ;(A4 also points to the current window.)
MOVEQ #4,D2
TST.B D3 ;If this is WMgrPort, check only the port variables.
BEQ.S @13
MOVEQ #10,D2
CMP.W #dialogKind,windowKind(A0)
;Is this a dialog window?
BNE.S @13 ;NO.
MOVEQ #12,D2 ;YES. There is one more handle to be checked.
@13 LEA Heap.V2,A1 ;Check each handle in turn.
MOVEQ #0,D0
MOVEQ #-1,D1
@14 ADDQ.W #1,D1
MOVE.B (A1)+,D0
CMP.L 0(A0,D0),A6
BEQ.S @30 ;There is a match.
DBRA D2,@14
TST.B D3 ;If this is WMgrPort, begin scanning the window
BEQ.S @51 ;list.
CMP.W #dialogKind,windowKind(A4)
;Is this a dialog window?
BNE.S @21 ;NO.
MOVE.L items(A4),A0
BSR IndirectA0 ;Get the item list.
BCS.S @21
TST.B (A0) ;Don't bother checking if there are more than 256
BNE.S @21 ;items.
MOVE.W (A0)+,D0
MOVEQ #0,D2
@20 CMP.L (A0)+,A6
BEQ.S @31 ;There is a match.
ADD.W #9,A0 ;Skip past the other items and the string to the
MOVEQ #0,D1 ;next handle.
MOVE.B (A0),D1
ADDQ.W #1,D1
BSET #0,D1
ADD.W D1,A0
ADDQ.W #1,D2
DBRA D0,@20
@21 LEA wControlList(A4),A0 ;Prepare to scan the control list.
@22 MOVE.L (A0),A0
CMP.L A0,A6 ;Does this control match the handle?
BEQ.S @33
BSR.S IndirectA0 ;NO. Go check the next one.
BCC.S @22
BRA.S @12
@31 BSR.S Heap.WString ;Identify the current window.
MOVEQ #Heap.DI-Heap..,D7
BSR.S Heap.toPString
MOVE.W D2,D0
BSR.S @32 ;Print the item number.
MOVEQ #Heap.DI2-Heap..,D7
BSR.S Heap.toPString
MOVE.B 8(A0),D0
@32 JMP _Put2Dig
@33 BSR.S Heap.WString ;Identify the current window and just print that
MOVEQ #Heap.Control-Heap..,D7 ;this control belongs to that window.
Heap.toPString BRA Heap.PString
Heap.WString
MOVE.W D1,-(SP) ;Identify the current window.
TST.B D3
BNE.S @1
MOVE.B #'(',(A2)+ ;This is the WMgrPort.
MOVEQ #Heap.WMgrPort-Heap..,D7
BSR.S Heap.toPString
MOVEQ #Heap.RP8Spaces-Heap..,D7
BSR.S Heap.toPString
BRA.S @2
@1 MOVEQ #Heap.W2-Heap..,D7 ;Print the address of the current window.
BSR.S Heap.toPString
MOVE.L A4,D0
JSR _Put6Dig ;Give the address of the window.
MOVEQ #Heap.RPSpace-Heap..,D7
BSR.S Heap.toPString
@2 MOVE.W (SP)+,D1
RTS
;+-----------------------------------------------------+
;| Dereference A0, checking it to make sure it is even |
;| and non-NIL both before and after dereferencing. |
;+-----------------------------------------------------+
;|
;|ENTRY: IndirectA0
;|
;|IN: A0: pointer
;|
;|OUT: Carry set A0: or (A0:) was NIL or odd.
;| A0' unpredictable.
;| Carry clear otherwise
;| A0' (A0:)
;|
;|Destroys D7.
;|
;|
;+----------------------------------------+
;| Make sure that A0 is even and non-NIL. |
;+----------------------------------------+
;|
;|ENTRY: CheckA0
;|
;|IN: A0: pointer
;|
;|OUT: Carry set A0: was NIL or odd.
;| Carry clear otherwise
;|
;|Destroys D7.
;|
IndirectA0 BSR.S CheckA0 ;Check A0 before dereferencing.
BCS.S CheckA0.RTS ;If error do nothing.
MOVE.L (A0),A0 ;Dereference it and check again.
CheckA0 MOVE.L A0,D7 ;Make sure that A0 is both non-NIL and even.
BEQ.S @1
LSR.B #1,D7
RTS
@1 SUBQ.L #1,D7 ;Set the carry flag if it isn't.
CheckA0.RTS RTS
;##########################
;## ##
;## Discipline section ##
;## ##
;##########################
DisciplineInit
LEA updating,A0
CLR.L (A0) ;Initialize the Begin/EndUpdate.
RTS
retOK
MOVEQ #0,D7
RTS
retErr
MOVE #%01000,CCR ;Set the N bit to 1.
RTS
MACRO ErrText code,string =
err{code} TRAPMon '? {string}'
retErr{code} MOVE.W #err{code}-A,D7
BRA retErr
|
CheckRAM
;Given an address in D0, this checks to see if it is even.
;It also checks that it is between 0 and MemTop.
;It returns D0 with the high byte masked off.
BTST #0,D0 ;odd address
BNE.S retErrOdd
CheckOddRAM
AND.L Lo3Bytes,D0 ;mask off high byte
BEQ.S retErrZero
CheckRAM.
CMP.L RealMemTop,D0
BHS.S retErrAddress ;too high
BRA.S retOK
ErrText Zero,NIL address
ErrText Odd,odd address
ErrText Address,address
CheckROM
;Given an address in D0, this checks to see if it is even.
;It also checks that it is between $400000 and $40FFFF.
;It returns D0 with the high byte masked off.
BTST #0,D0 ;odd address
BNE.S retErrOdd
CheckOddROM
AND.L Lo3Bytes,D0 ;mask off high byte
BEQ.S retErrZero
CheckROM.
CMP.L #$400000,D0
BLO.S retErrAddress ;too low
CMP.L #$410000,D0
BHS.S retErrAddress ;too high
BRA retOK
CheckAddress
BSR CheckRAM
BPL.S @1
BSR.S CheckROM.
@1
RTS
CheckOddAddress
BSR CheckOddRAM
BPL.S @1
BSR CheckROM.
@1
RTS
CheckString
BSR.S CheckOddAddress
BMI retErrString
MOVE.L D0,A0
ADD.B (A0),D0
BSR.S CheckOddAddress
BMI retErrStringLength
RTS
ErrText String,string
ErrText StringLength,string length
CheckJT
BSR CheckRAM
BMI.S retErrJT
CMP.L BufPtr,D0
BHS.S retErrJT
SUB.L CurrentA5,D0
BLO.S retErrJT
MOVEQ #0,D1
MOVE.W CurJTOffset,D1
SUB.L D1,D0
BLO.S retErrJT
AND.B #3,D0
SUBQ.B #2,D0
BNE.S retErrJT
BRA retOK
ErrTExt JT,jump table
CheckZone
;Given a heap zone address in D0, this checks to see that D0 is a valid
;heap zone pointer.
;It trashes register D0. A1 is set to point to the zone header.
BSR CheckRAM
BMI.S retErrZonePtr
MOVE.L D0,A1 ;check fields of this heap
ADD.L #heapData,D0 ;point to the first byte of the heap
CMP.L bkLim(A1),D0 ;get the top of the heap
BHS.S retErrZone ;if the header is too high, it is screwed up
MOVE.L bkLim(A1),D0
BSR CheckRAM
BMI.S retErrZone
RTS
ErrText ZonePtr,THz
ErrText Zone,Zone
CheckBlock
;Given a heap zone address in D0 and a block pointer in A0, this checks
;to see that D0 is a valid heap zone pointer and that A0 falls within
;the zone.
;It trashes registers A1 and D0.
CMP.L D0,A0 ;compare with the header
BLO retErr
BSR.S CheckZone
BMI retErr
CMP.L bkLim(A1),A0 ;compare with the top of the heap
BHS retErr
BRA retOK
CheckPtr
;Given an address in D0, this checks to see if it is a valid pointer.
;It trashes registers D0, A0 and A1.
BSR CheckRAM
BMI.S retErrPtr ;check if pointer is good at all
MOVE.L D0,A0 ;look at block more closely
MOVE.B tagBC-blkData(A0),D0
AND.B #tybkMask<<6,D0 ;get the block type
CMP.B #tybkNRel<<6,D0 ;is is a non-relocatable?
BNE.S retErrPtr
MOVE.L handle-blkData(A0),D0
BSR.S CheckBlock ;get a pointer to the heap zone
BMI.S retErrPtr
RTS
ErrText Ptr,Ptr
CheckHandle
;Given an address in D0, this checks to see if it is a valid handle.
;It trashes registers D0, A0 and A1.
BSR CheckRAM
BMI.S retErrHandle
MOVE.L D0,A1 ;save the master pointer address for later
MOVE.L D0,A0
MOVE.L (A0),D0 ;deref handle
BEQ retOK ;purged handle is OK (master pointer=0)
BSR CheckRAM
BMI.S retErrHandle ;check if master pointer is valid
MOVE.L D0,A0 ;look at block more closely
MOVE.B tagBC-blkData(A0),D0
AND.B #tybkMask<<6,D0 ;get the block type
CMP.B #tybkRel<<6,D0 ;is is a relocatable?
BNE.S retErrHandle
MOVE.L A1,D0 ;get a pointer to the heap zone
SUB.L handle-blkData(A0),D0
BSR.S CheckBlock ;by subtracting the relative handle
BMI.S retErrHandle ;from the absolute handle and check it
RTS
ErrText Handle,Handle
CheckFakeHandle
;This is just like CheckHandle except the handle can be a "fake" one.
BSR CheckAddress
BMI.S retErrHandle
MOVE.L D0,A0
MOVE.L (A0),D0
BEQ retOK
BSR CheckAddress
BMI.S retErrHandle
RTS
CheckFullHandle
;This is just like CheckHandle except the handle cannot be empty.
MOVE.L D0,-(SP)
BSR.S CheckHandle
MOVEA.L (SP)+,A0
BMI.S retErrHandle
MOVE.L (A0),D0
AND.L Lo3Bytes,D0
BEQ.S retErrEmptyHandle
BRA retOK
ErrText EmptyHandle,empty Handle
CheckFakeFullHandle
;This is just like CheckFullHandle except the handle can be a "fake" one.
BSR CheckAddress
BMI retErrHandle
MOVE.L D0,A0
MOVE.L (A0),D0
BSR CheckAddress
BMI retErrHandle
RTS
CheckRect
;Given a pointer to a rectangle in D0, it checks that it is sensible.
;It trashes A0 and returns the right-left value in D0 if it is successful.
BSR CheckAddress
BMI.S retErrRectPtr
CheckRect.
MOVE.L D0,A0
MOVE.W bottom(A0),D0
SUB.W top(A0),D0
BLT.S retErrRect
MOVE.W right(A0),D0
SUB.W left(A0),D0
BLT.S retErrRect
BRA retOK
ErrText RectPtr,^Rect
ErrText Rect,Rect
CheckBitMap
;Given a bit map pointer in D0, this checks that it is a valid bit map.
BSR CheckAddress
BMI.S retErrBitMapPtr
CheckBitMap.
MOVE.L D0,A1
MOVE.L baseAddr(A1),D0
BSR CheckAddress
BMI.S retErrBaseAddr
MOVE.L A1,D0
ADD.L #bounds,D0
BSR CheckRect.
BMI.S retErrBounds
MOVE.W rowBytes(A1),D1
BTST #0,D1
BNE retErrRowBytes
MOVE.W bounds+bottom(A1),D0
SUB.W bounds+top(A1),D0
MULU D1,D0 ;calculate the size of this bitmap
AND.L #$FFFF,D0 ;mask off the low word
ADD.L baseAddr(A1),D0 ;calculate the last address of this bitmap
BSR CheckAddress
BMI.S retErrBitMap
RTS
ErrText BitMapPtr,^BitMap
ErrText BitMap,BitMap
ErrText BaseAddr,baseAddr
ErrText Bounds,bounds
ErrText RowBytes,rowBytes
CheckCursor
;Given a cursor pointer in D0, this checks the hot spot.
BSR CheckAddress
BMI.S retErrCursorPtr
CheckCursor.
MOVE.L D0,A0 ;point to that hot spot
MOVE.W hotSpot+h(A0),D0
CMP.W #16,D0
BHI.S retErrHotSpot
MOVE.W hotSpot+v(A0),D0
CMP.W #16,D0
BHI.S retErrHotSpot
BRA retOK
ErrText CursorPtr,^Cursor
ErrText HotSpot,hotSpot
CheckPPR
;Given an address in D0, this checks if it is a good Region or Picture
;or Polygon.
;It trashes A0, A1, D0 and D1.
MOVE.L D0,D1
BSR CheckFullHandle
BMI.S @1
MOVE.L D1,A0
MOVE.L (A0),A0
MOVE.W (A0)+,D0 ;get the PPR length
CMP.W #10,D0
BLT retErr ;good lengths are >= 10
MOVE.L A0,D0 ;get the PPR pointer
BSR CheckRect.
@1
RTS
CheckPict
BSR.S CheckPPR
BMI.S retErrPict
RTS
ErrText Pict,PicHandle
CheckPoly
BSR.S CheckPPR
BMI.S retErrPoly
RTS
ErrText Poly,PolyHandle
CheckRgn
BSR.S CheckPPR
BMI.S retErrRgn
RTS
ErrText Rgn,RgnHandle
CheckPort
;Given a grafPort in D0, this checks just about every thing that you
;can check.
BSR CheckRAM
BMI.S retErrPort
CheckPort.
MOVE.L D0,A2 ;point to the port
ADD.L #portBits,D0 ;point to the bitMap
BSR CheckBitMap.
BMI @3
MOVE.L A2,D0
ADD.L #portRect,D0 ;point to the rectangle
BSR CheckRect.
BMI.S retErrPortRect
MOVE.L visRgn(A2),D0 ;check this region
BSR CheckRgn
BMI.S retErrVisRgn
MOVE.L clipRgn(A2),D0 ;check this region
BSR CheckRgn
BMI.S retErrClipRgn
MOVE.L grafProcs(A2),D0
BEQ.S @2
BSR CheckAddress
BMI.S retErrGrafProcs
MOVE.L D0,A0
MOVEQ #13-1,D1
@1
MOVE.L (A0)+,D0
BSR CheckAddress
BMI.S retErrGrafProcs
DBRA D1,@1
@2
BRA retOK
@3
RTS
ErrText Port,GrafPtr
ErrText PortRect,portRect
ErrText VisRgn,visRgn
ErrText ClipRgn,clipRgn
ErrText GrafProcs,grafProcs
CheckWindow
BSR CheckAddress
BMI retErrWindow
CheckWindow.
BSR CheckPort.
BMI @4
MOVE.L structRgn(A2),D0 ;check this region
BSR CheckRgn
BMI retErrStructRgn
MOVE.L contRgn(A2),D0 ;check this region
BSR CheckRgn
BMI retErrContRgn
MOVE.L updateRgn(A2),D0 ;check this region
BSR CheckRgn
BMI retErrUpdateRgn
MOVE.L windowDef(A2),D0 ;check the defProc
BSR CheckFakeHandle
BMI retErrDefProc
MOVE.L wTitleHandle(A2),D0 ;check the title
BEQ.S @1
BSR CheckFullHandle
BMI retErrWTitle
@1
MOVE.L wControlList(A2),D0 ;check the control list
BEQ.S @2
BSR CheckFullHandle
BMI retErrControlList
@2
MOVE.L nextWindow(A2),D0 ;check the next window
BEQ.S @3
BSR CheckRAM
BMI retErrNextWindow
@3
MOVE.L windowPic(A2),D0 ;check the picture handle
BEQ.S @4
BSR CheckFullHandle
BMI retErrWindowPic
@4
RTS
ErrText Window,WindowPtr
ErrText StructRgn,strucRgn
ErrText ContRgn,contRgn
ErrText UpdateRgn,updateRgn
ErrText WTitle,titleHandle
ErrText ControlList,controlList
ErrText NextWindow,nextWindow
ErrText WindowPic,windowPic
CheckBehind
TST.L D0
BEQ retOK
CMP.L MinusOne,D0 ;-1 is also OK
BEQ retOK
BSR CheckWindow
RTS
CheckControl
MOVE.L D0,A2
BSR CheckFullHandle
BMI retErrControl
CheckControl.
MOVE.L (A2),D0
ADD.L #contrlRect,D0 ;point to the rectangle
BSR CheckRect.
BMI retErrContrlRect
MOVE.L (A2),A2
MOVE.L nextControl(A2),D0 ;check the nextControl
BEQ.S @1
BSR CheckFullHandle
BMI retErrNextControl
@1
MOVE.L contrlDefHandle(A2),D0 ;check the defProc
BSR CheckFakeHandle
BMI retErrDefProc
MOVE.L contrlAction(A2),D0 ;check the actionProc
BEQ.S @2
CMP.L MinusOne,D0 ;-1 is ok, too
BEQ.S @2
BSR CheckAddress
BMI.S retErrAction
@2
MOVE.L contrlOwner(A2),D0 ;check the owner
BSR CheckRAM
BMI.S retErrContrlOwner
RTS
ErrText Control,ControlHandle
ErrText ContrlRect,contrlRect
ErrText NextControl,nextControl
ErrText Action,actionProc
ErrText ContrlOwner,contrlOwner
CheckMenu
MOVE.L D0,A2
BSR CheckFullHandle
BMI.S retErrMenu
MOVE.L (A2),A2
MOVE.L menuDefHandle(A2),D0 ;check the menu defProc
BSR CheckFakeHandle
BMI.S retErrDefProc
RTS
ErrText Menu,MenuHandle
ErrText DefProc,defProc handle
CheckTERec
MOVE.L D0,A2
BSR CheckFullHandle
BMI.S retErrTE
MOVE.L (A2),D0
ADD.L #teDestRect,D0 ;point to the rectangle
BSR CheckRect.
BMI retErrDestRect
MOVE.L (A2),D0
ADD.L #teViewRect,D0 ;point to the rectangle
BSR CheckRect.
BMI retErrViewRect
MOVE.L (A2),A2
MOVE.L teTextH(A2),D0 ;check the text
BSR CheckFullHandle
BMI retErrTextH
MOVE.L teWordBreak(A2),D0
BEQ.S @1
BSR CheckAddress
BMI retErrWordBreak
@1
MOVE.L teClikProc(A2),D0
BEQ.S @2
BSR CheckAddress
BMI retErrClikProc
@2
MOVE.L teHiHook(A2),D0
BEQ.S @3
BSR CheckAddress
BMI retErrHiHook
@3
MOVE.L teCarHook(A2),D0
BEQ.S @4
BSR CheckAddress
BMI retErrCarHook
@4
MOVE.L teGrafPort(A2),D0
BSR CheckRAM
BMI retErrInPort
RTS
ErrText TE,TEHandle
ErrText DestRect,destRect
ErrText ViewRect,viewRect
ErrText TextH,text handle
ErrText WordBreak,wordBreak
ErrText ClikProc,clikLoop
ErrText HiHook,highHook
ErrText CarHook,caretHook
ErrText InPort,TE GrafPtr
CheckDialog
BSR CheckAddress
BMI.S retErrDialog
CheckDialog.
BSR CheckWindow.
BMI @1
MOVE.L items(A2),D0
BSR CheckFullHandle
BMI.S retErrItemList
MOVE.L teHandle(A2),D0
BEQ.S @1
BSR CheckFullHandle
BMI.S retErrEditText
@1
RTS
ErrText Dialog,DialogPtr
ErrText ItemList,item list
ErrText EditText,editText item
;+------------------------------------------------------------------+
;| The following code is for actual use of the Check... code above. |
;+------------------------------------------------------------------+
ROMA0
MOVE.L RegA0,D0 ;get ROM location in register
.CheckROM BRA CheckROM
RAMA0
MOVE.L RegA0,D0 ;get RAM location in register
.CheckRAM BRA CheckRAM
RAMA1
MOVE.L RegA1,D0 ;get RAM location in register
BRA.S .CheckRAM
RAM0
MOVE.L Stack0,D0 ;get RAM location in register
BRA.S .CheckRAM
RAM2
MOVE.L Stack2,D0 ;get RAM location in register
BRA.S .CheckRAM
RAM4
MOVE.L Stack4,D0 ;get RAM location in register
BRA.S .CheckRAM
RAM6
MOVE.L Stack6,D0 ;get RAM location in register
BRA.S .CheckRAM
RAM8
MOVE.L Stack8,D0 ;get RAM location in register
BRA.S .CheckRAM
RAM22
MOVE.L Stack22,D0 ;get RAM location in register
BRA.S .CheckRAM
OddRAMA0
MOVE.L RegA0,D0 ;get RAM location in register
.CheckOddRAM BRA CheckOddRAM
OddRAM4
MOVE.L Stack4,D0 ;get RAM location in register
BRA.S .CheckOddRAM
AddressA0
MOVE.L RegA0,D0 ;get address in register
.CheckAddress BRA CheckAddress
AddressA1
MOVE.L RegA1,D0 ;get address in register
BRA.S .CheckAddress
Address0
MOVE.L Stack0,D0 ;get address in register
BRA.S .CheckAddress
Address4
MOVE.L Stack4,D0 ;get address in register
BRA.S .CheckAddress
Address8
MOVE.L Stack8,D0 ;get address in register
BRA.S .CheckAddress
Address10
MOVE.L Stack10,D0 ;get address in register
BRA.S .CheckAddress
Address16
MOVE.L Stack16,D0 ;get address in register
BRA.S .CheckAddress
OddAddressA0
MOVE.L RegA0,D0 ;get address in register
.CheckOddAddress
BRA CheckOddAddress
OddAddress0
MOVE.L Stack0,D0 ;get address in register
BRA.S .CheckOddAddress
OddAddress4
MOVE.L Stack4,D0 ;get address in register
BRA.S .CheckOddAddress
OddAddress8
MOVE.L Stack8,D0 ;get address in register
BRA.S .CheckOddAddress
OddAddress12
MOVE.L Stack12,D0 ;get address in register
BRA.S .CheckOddAddress
StringA0
MOVE.L RegA0,D0 ;get string in register
.CheckString BRA CheckString
String0
MOVE.L Stack0,D0 ;get string in register
BRA.S .CheckString
String2
MOVE.L Stack2,D0 ;get string in register
BRA.S .CheckString
String4
MOVE.L Stack4,D0 ;get string in register
BRA.S .CheckString
String10
MOVE.L Stack10,D0 ;get string in register
BRA.S .CheckString
String14
MOVE.L Stack14,D0 ;get string in register
BRA.S .CheckString
String16
MOVE.L Stack16,D0 ;get string in register
BRA.S .CheckString
String18
MOVE.L Stack18,D0 ;get string in register
BRA.S .CheckString
String20
MOVE.L Stack20,D0 ;get string in register
BRA.S .CheckString
String26
MOVE.L Stack26,D0 ;get string in register
BRA.S .CheckString
JTPC
MOVE.L RegPC,D0
.CheckJT BRA CheckJT
JT0
MOVE.L Stack0,D0
BRA.S .CheckJT
ZoneA0
MOVE.L RegA0,D0
.CheckZone BRA CheckZone
PtrA0
MOVE.L RegA0,D0 ;get handle in register
.CheckPtr BRA CheckPtr
Ptr0
MOVE.L Stack0,D0 ;get handle in register
BRA.S .CheckPtr
HandleA0
MOVE.L RegA0,D0 ;get handle in register
.CheckHandle BRA CheckHandle
Handle0
MOVE.L Stack0,D0 ;get handle in register
BRA.S .CheckHandle
Handle4
MOVE.L Stack4,D0 ;get handle in register
BRA.S .CheckHandle
FullHandleA0
MOVE.L RegA0,D0 ;get handle in register
.CheckFullHandle
BRA CheckFullHandle
FullHandleA1
MOVE.L RegA1,D0 ;get handle in register
BRA.S .CheckFullHandle
FullHandle0
MOVE.L Stack0,D0 ;get handle in register
BRA.S .CheckFullHandle
FullHandle2
MOVE.L Stack2,D0 ;get handle in register
BRA.S .CheckFullHandle
FullHandle4
MOVE.L Stack4,D0 ;get handle in register
BRA.S .CheckFullHandle
FullHandle8
MOVE.L Stack8,D0 ;get handle in register
BRA.S .CheckFullHandle
FullHandle10
MOVE.L Stack10,D0 ;get handle in register
BRA.S .CheckFullHandle
FakeFullHandle0
MOVE.L Stack0,D0 ;get handle in register
.CheckFakeFullHandle
BRA CheckFakeFullHandle
Cursor0
MOVE.L Stack0,D0 ;get cursor location in register
.CheckCursor BRA CheckCursor
Rect0
MOVE.L Stack0,D0 ;get rectangle in register
.CheckRect BRA CheckRect
RTS
Rect2
MOVE.L Stack2,D0 ;get rectangle in register
BRA.S .CheckRect
Rect4
MOVE.L Stack4,D0 ;get rectangle in register
BRA.S .CheckRect
Rect6
MOVE.L Stack6,D0 ;get rectangle in register
BRA.S .CheckRect
Rect8
MOVE.L Stack8,D0 ;get rectangle in register
BRA.S .CheckRect
Rect10
MOVE.L Stack10,D0 ;get rectangle in register
BRA.S .CheckRect
Rect18
MOVE.L Stack18,D0 ;get rectangle in register
BRA.S .CheckRect
Rect22
MOVE.L Stack22,D0 ;get rectangle in register
BRA.S .CheckRect
Rgn0
MOVE.L Stack0,D0 ;get region in register
.CheckRgn BRA CheckRgn
Rgn4
MOVE.L Stack4,D0 ;get region in register
BRA.S .CheckRgn
Rgn8
MOVE.L Stack8,D0 ;get region in register
BRA.S .CheckRgn
Rgn18
MOVE.L Stack18,D0 ;get region in register
BRA.S .CheckRgn
Poly0
MOVE.L Stack0,D0 ;get polygon in register
.CheckPoly BRA CheckPoly
Poly4
MOVE.L Stack4,D0 ;get polygon in register
BRA.S .CheckPoly
Poly8
MOVE.L Stack8,D0 ;get polygon in register
BRA.S .CheckPoly
Pict0
MOVE.L Stack0,D0 ;get picture in register
.CheckPict BRA CheckPict
Pict4
MOVE.L Stack4,D0 ;get picture in register
BRA.S .CheckPict
Port0
MOVE.L Stack0,D0 ;get port in register
.CheckPort BRA CheckPort
Window0
MOVE.L Stack0,D0 ;get window in register
.CheckWindow BRA CheckWindow
Window2
MOVE.L Stack2,D0 ;get window in register
BRA.S .CheckWindow
Window4
MOVE.L Stack4,D0 ;get window in register
BRA.S .CheckWindow
Window6
MOVE.L Stack6,D0 ;get window in register
BRA.S .CheckWindow
Window8
MOVE.L Stack8,D0 ;get window in register
BRA.S .CheckWindow
Window22
MOVE.L Stack22,D0 ;get window in register
BRA.S .CheckWindow
Behind0
MOVE.L Stack0,D0 ;check the behind field
.CheckBehind BRA CheckBehind
Behind6
MOVE.L Stack6,D0 ;check the behind field
BRA.S .CheckBehind
Behind10
MOVE.L Stack10,D0 ;check the behind field
BRA.S .CheckBehind
Dialog0
MOVE.L Stack0,D0 ;check the dialog
.CheckDialog BRA CheckDialog
Dialog6
MOVE.L Stack6,D0 ;check the dialog
BRA.S .CheckDialog
Dialog12
MOVE.L Stack12,D0 ;check the dialog
BRA.S .CheckDialog
Dialog14
MOVE.L Stack14,D0 ;check the dialog
BRA.S .CheckDialog
Menu0
MOVE.L Stack0,D0 ;get menu handle in register
.CheckMenu BRA CheckMenu
Menu2
MOVE.L Stack2,D0 ;get menu handle in register
BRA.S .CheckMenu
Menu4
MOVE.L Stack4,D0 ;get menu handle in register
BRA.S .CheckMenu
Menu6
MOVE.L Stack6,D0 ;get menu handle in register
BRA.S .CheckMenu
Control0
MOVE.L Stack0,D0 ;get control handle in register
.CheckControl BRA CheckControl
Control2
MOVE.L Stack2,D0 ;get control handle in register
BRA.S .CheckControl
Control4
MOVE.L Stack4,D0 ;get control handle in register
BRA.S .CheckControl
Control8
MOVE.L Stack8,D0 ;get control handle in register
BRA.S .CheckControl
Control14
MOVE.L Stack14,D0 ;get control handle in register
BRA.S .CheckControl
ProcA0
MOVE.L RegA0,D0 ;get the proc into a register
.CheckProc BEQ retOK
BRA CheckAddress
Proc0
MOVE.L Stack0,D0 ;get the proc into a register
BRA.S .CheckProc
Proc4
MOVE.L Stack4,D0 ;get the proc into a register
BRA.S .CheckProc
TERec0
MOVE.L Stack0,D0 ;get TERec handle in register
.CheckTERec BRA CheckTERec
BitMap0
MOVE.L Stack0,D0 ;get bitmap pointer in register
.CheckBitMap BRA CheckBitMap
BitMap14
MOVE.L Stack14,D0 ;get bitmap pointer in register
BRA.S .CheckBitMap
BitMap18
MOVE.L Stack18,D0 ;get bitmap pointer in register
BRA.S .CheckBitMap
;+-----------------------------------------------+
;| These are the trap-specific checking routines |
;+-----------------------------------------------+
SetTrapAddress
BSR ROMA0 ;if it is ROM, it's fine
BPL.S @1
MOVE.L D0,A0
MOVE.L SysZone,D0 ;check if this routine is in the system heap
BSR CheckBlock
BMI.S retErrSysZone
@1
RTS
ErrText SysZone,not in SysZone
EqualRect
Address4Address0
BSR Address4
BMI.S @1
BSR Address0
@1
RTS
TENew
Rect4Rect0
BSR Rect4 ;check one of the rectangles
BMI.S @1
BSR Rect0 ;check the other rectangle
@1
RTS
ScalePt
MapPt
BSR RAM8 ;check the ram address
BMI.S @1
BSR Rect4Rect0 ;check the two rectangles
@1
RTS
FillRect
FillOval
Rect4RAM0
BSR Rect4 ;check the rectangle
BMI.S @1
BSR RAM0 ;check the other pointer
@1
RTS
FillRoundRect
FillArc
PtToAngle
BSR Rect8 ;check the rectangle
BMI.S @1
BSR RAM0 ;check the other pointer
@1
RTS
SectRect
UnionRect
BSR Address8
BMI.S @1
BSR Address4
BMI.S @1
BSR RAM0 ;check the destination
@1
RTS
MapRect
BSR Address8 ;check the destination "rectangle"
BMI.S @1
BSR Rect4Rect0 ;check the mapping rectangles
@1
RTS
FillPoly
BSR Poly4 ;check the polygon
BMI.S @1
BSR RAM0 ;check the other pointer
@1
RTS
FillRgn
BSR Rgn4 ;check the region
BMI.S @1
BSR RAM0 ;check the other pointer
@1
RTS
CopyRgn
EqualRgn
Rgn4Rgn0
BSR Rgn4 ;check one of the regions
BMI.S @1
BSR Rgn0 ;check the other region
@1
RTS
SectRgn
UnionRgn
DiffRgn
XorRgn
BSR Rgn8 ;check one of the regions
BMI.S @1
BSR Rgn4Rgn0 ;check the other two
@1
RTS
MapRgn
BSR Rgn8 ;check the region
BMI.S @1
BSR Rect4Rect0 ;check the two rectangles
@1
RTS
MapPoly
BSR Poly8 ;check the polygon
BMI.S @1
BSR Rect4Rect0 ;check the two rectangles
@1
RTS
RectRgn
BSR Rgn4 ;check if the destination is a region
BMI.S @1
BSR Address0 ;check the source
@1
RTS
RectInRgn
BSR Address4 ;check if the "rectangle"
BMI.S @1
BSR Rgn0 ;check if this is a region
@1
RTS
DrawPicture
BSR Pict4 ;check if the picture is a picture
BMI.S @1
BSR Rect0 ;check if the rect is a rectangle
@1
RTS
Rect10Rect6
BSR Rect10
BMI.S @1
BSR Rect6
@1
RTS
StdBits
StdBits.
BSR BitMap14
BMI.S @1
BSR Rect10Rect6
BMI.S @1
MOVE.L Stack0,D0 ;get the region into a register
BEQ retOK
BSR CheckRgn
@1
RTS
CopyBits
BSR BitMap18
BMI.S @1
BSR.S StdBits. ;check the rest of the parameters
@1
RTS
DragGrayRgn
DragTheRgn
BSR Rgn18
BMI.S @1
BSR Rect10Rect6
BMI.S @1
BSR Proc0 ;check the action proc
@1
RTS
CalcVis
SystemClick
ClipAbove
MOVE.L Stack0,D0 ;check the window parameter
BEQ retOK
BSR CheckWindow
RTS
CalcVisBehind
PaintOne
PaintBehind
MOVE.L Stack4,D0 ;check the window parameter
BEQ.S @1
BSR CheckWindow
BMI.S @2
@1
BSR Rgn0 ;check the region parameter
@2
RTS
NewWindow
MOVE.L Stack22,D0 ;check the window storage
BEQ.S @1
BSR CheckRAM
BMI.S @2
@1
BSR Rect18 ;check the window rectangle
BMI.S @2
BSR String14 ;check the window title
BMI.S @2
BSR Behind6 ;check the behind field
@2
RTS
DisposeWindow
BSR Window0 ;check the window
BMI.S @1
BSR Ptr0
@1
RTS
NewDialog
MOVE.L Stack26,D0 ;check the dialog storage
BEQ.S @1
BSR CheckRAM
BMI.S @2
@1
BSR Rect22 ;check the window rectangle
BMI.S @2
BSR String18 ;check the title
BMI.S @2
BSR Behind10 ;check the behind field
BMI.S @2
MOVE.L Stack0,D0 ;don't need an item handle just yet
BEQ retOK
BSR CheckFullHandle ;check the items handle
@2
RTS
DisposDialog
BSR Dialog0 ;check the dialog
BMI.S @1
BSR Ptr0
@1
RTS
GetNewWindow
GetNewDialog
MOVE.L Stack4,D0 ;check the storage
BEQ.S @1
BSR CheckRAM
BMI.S @2
@1
BSR Behind0
@2
RTS
GetWTitle
FindControl
Window4RAM0
BSR Window4 ;check the window
BMI.S @1
BSR RAM0 ;check the result place
@1
RTS
SetWTitle
BSR Window4 ;check the window
BMI.S @1
BSR String0 ;check the new title
@1
RTS
SendBehind
BSR Window4 ;check one window parameter
BMI.S @1
MOVE.L Stack0,D0
BEQ retOK
BSR CheckWindow ;check the behind parameter
@1
RTS
UpdateInit
LEA Updating,A0
MOVE.L (A0),D1
MOVE.L Stack0,D0
RTS
BeginUpdate
BSR.S UpdateInit
MOVE.L D0,(A0)
TST.L D1
BNE.S retErrBadBeginUpdate
BRA.S Update
EndUpdate
BSR.S UpdateInit
CLR.L (A0)
CMP.L D1,D0
BNE.S retErrBadEndUpdate
Update
BSR CheckPort
BMI.S @1
MOVE.L updateRgn(A2),D0 ;check this region
BSR CheckRgn
BMI retErrUpdateRgn
@1
RTS
ErrText BadBeginUpdate,no EndUpdate
ErrText BadEndUpdate,<> BeginUpdate
DragWindow
GrowWindow
BSR Window8 ;check the window
BMI.S @1
BSR Rect0 ;check the rectangle
@1
RTS
GetItemIcon
GetItemStyle
GetItemMark
GetItem
BSR Menu6 ;check the menu
BMI.S @1
BSR RAM0 ;check the address
@1
RTS
SetItem
BSR Menu6 ;check the menu
BMI.S @1
BSR String0 ;check the string
@1
RTS
PlotIcon
BSR Rect4 ;check the rectangle
BMI.S @1
BSR FakeFullHandle0 ;check the handle
@1
RTS
NewControl
BSR Window22 ;check the window
BMI.S @1
BSR Rect18 ;check the rectangle
BMI.S @1
BSR String14 ;check the title
@1
RTS
GetCTitle
BSR Control4 ;check the control
BMI.S @1
BSR RAM0 ;check the address
@1
RTS
SetCTitle
BSR FullHandle4 ;check the control
BMI.S @1
BSR String0
@1
RTS
DragControl
BSR Control14 ;check the control
BMI.S @1
BSR Rect6 ;check the limitRect
BMI.S @1
BSR Rect2 ;check the slopRect
@1
RTS
Dequeue
Enqueue
BSR RAMA0
BMI.S @1
BSR RAMA1
@1
RTS
DialogSelect
BSR Address8 ;check the event
BMI.S DialogSelectRTS
RAM4RAM0
BSR RAM4 ;check one result
BMI.S DialogSelectRTS
BSR RAM0 ;check the other
DialogSelectRTS
RTS
GetAppParms
RAM8RAM4RAM0
BSR RAM8 ;check another
BMI.S @1
BSR.S RAM4RAM0 ;check more
@1
RTS
GetResInfo
GetResInfo.
MOVE.L Stack8,D0
BEQ.S @1
BSR CheckRAM
BMI.S @3
@1
MOVE.L Stack4,D0
BEQ.S @2
BSR CheckRAM
BMI.S @3
@2
MOVE.L Stack0,D0
BEQ retOK
BSR CheckRAM
@3
RTS
GetDItem
BSR Dialog14 ;check the dialog first
BMI.S @1
BSR.S GetResInfo. ;check the other parameters
@1
RTS
SetDItem
BSR Dialog12 ;check the dialog first
BMI.S @1
MOVE.W Stack8,D0 ;check the item type we are setting
AND.W #$7F,D0 ;extract the type
BEQ.S @2 ;userItem (0) is a special case
BSR FullHandle4 ;check the item handle
BMI.S @1
BRA.S @3
@2
MOVE.L Stack4,D0
BEQ.S @3
BSR CheckAddress ;check the userItem proc
BMI.S @1
@3
BSR Rect0 ;check the rectangle
@1
RTS
ModalDialog
BSR Proc4 ;check the filterProc
BMI.S @1
BSR RAM0 ;check the result address
@1
RTS
TEUpdate
BSR Rect4 ;check the update rect
BMI.S @1
BSR TERec0
@1
RTS
PtrToHand
BSR OddAddressA0
BMI.S @1
TST.B RegD0
BNE retErrLength
ADD.L RegD0,D0
BSR CheckOddAddress
BMI retErrLength
@1
RTS
PtrToXHand
PtrAndHand
BSR FullHandleA1
BMI.S @1
BSR PtrToHand
@1
RTS
HandAndHand
BSR FullHandleA0
BMI.S @1
BSR FullHandleA1
@1
RTS
GetScrap
MOVE.L Stack8,D0
BEQ.S @1
BSR CheckFullHandle ;check the destination handle
BMI.S @2
@1
BSR RAM0 ;check the offset destination
@2
RTS
PB
BSR RAMA0
BMI.S retErrParamBlock
MOVE.L RegA0,A0
MOVE.L RegPC,A1 ;get the old PC value
BTST #asyncTrpBit,(A1)
BEQ.S @1
MOVE.L ioCompletion(A0),D0
BEQ.S @1
BSR CheckAddress
BMI.S retErrCompletion
@1
BRA retOK
ErrText ParamBlock,ParamBlock
ErrText Completion,ioCompletion
Open
OpenRF
Create
Delete
SetFileInfo
SetFilLock
RstFilLock
SetFilType
BSR PB
BMI.S @1
MOVE.L ioFileName(A0),D0
BSR CheckString
BMI.S retErrFileName
@1
RTS
ErrText FileName,file name
Read
BSR PB
BMI.S @1
TST.L ioReqCount(A0)
BEQ retOK
MOVE.L ioBuffer(A0),D0
BSR CheckOddRAM
BMI.S retErrBuffer
ADD.L ioReqCount(A0),D0
SUBQ.L #1,D0
BSR CheckOddRAM
BMI.S retErrBuffer
@1
RTS
ErrText Buffer,ioBuffer
Write
BSR PB
BMI.S @1
TST.L ioReqCount(A0)
BEQ retOK
MOVE.L ioBuffer(A0),D0
BSR CheckOddAddress
BMI.S retErrBuffer
ADD.L ioReqCount(A0),D0
SUBQ.L #1,D0
BSR CheckOddAddress
BMI.S retErrBuffer
@1
RTS
SetVol
UnmountVol
FlushVol
Eject
OffLine
BSR PB
BMI.S @1
MOVE.L ioVNPtr(A0),D0
BEQ retOK
BSR CheckString
BMI.S retErrVolName
@1
RTS
ErrText VolName,volume name
GetVolInfo
GetVol
BSR PB
BMI.S @1
MOVE.L ioVNPtr(A0),D0
BEQ retOK
BSR CheckOddRAM
BMI.S retErrVolName
@1
RTS
Rename
BSR PB
BMI.S @1
MOVE.L ioNewName(A0),D0
BSR CheckString
BMI.S retErrNewName
@1
RTS
ErrText NewName,new name
GetFileInfo
BSR PB
BMI.S @1
TST.W ioFDirIndex(A0)
BMI.S @2
BEQ.S @2
TST.L ioFileName(A0)
BEQ retOK
@2
MOVE.L ioFileName(A0),D0
BSR CheckOddAddress
BMI retErrFileName
@1
RTS
InitZone
BSR AddressA0
BMI.S @1
MOVE.L D0,A0
MOVE.L startPtr(A0),D0
BSR CheckRAM
BMI.S retErrStartPtr
MOVE.L limitPtr(A0),D0
ADD.L #10,D0
BSR CheckRAM
BMI.S retErrLimitPtr
MOVE.L pGrowZone(A0),D0
BEQ.S @2
BSR CheckAddress
BMI.S retErrGrowZone
@2
MOVEQ #0,D0
MOVE.W cMoreMasters(A0),D0
NEG.L D0
ASL.L #2,D0
SUB.L #52,D0
SUB.L startPtr(A0),D0
ADD.L limitPtr(A0),D0
BMI.S retErrSmallZone
BRA retOK
@1
RTS
ErrText StartPtr,startPtr
ErrText LimitPtr,limitPtr
ErrText GrowZone,pGrowZone
ErrText SmallZone,zone too small
RecoverHandle
BSR RAMA0
BMI.S @1
MOVE.L D0,A0
MOVE.L handle-blkData(A0),D0
ADD.L TheZone,D0
BSR CheckHandle
@1
RTS
SetApplLimit
MOVE.L RegA0,D0
SUBQ.L #2,D0
BSR CheckRAM
RTS
BlockMove.
TST.L RegD0
BEQ retOK
MOVE.L RegA0,D0
BSR CheckOddAddress
BMI.S @1
ADD.L RegD0,D0
SUBQ.L #1,D0
BSR CheckOddAddress
BMI.S retErrLength
MOVE.L RegA1,D0
BSR CheckOddRAM
BMI.S @1
ADD.L RegD0,D0
SUBQ.L #1,D0
BSR CheckOddRAM
BMI.S retErrLength
@1
RTS
ErrText Length,length
VInstall.
VRemove
BSR RAMA0
BMI.S @1
MOVE.L D0,A0
MOVE.L vblAddr(A0),D0
BSR CheckAddress
BMI.S retErrVBL
@1
RTS
ErrText VBL,vblAddr
WriteParam
LEA SysParam,A0
CMP.L RegA0,A0
BNE.S retErrSysParam
MOVEQ #-1,D0
CMP.L RegD0,D0
BNE retErrMinusOne
BRA retOK
ErrText SysParam,SysParam
ErrText MinusOne,MinusOne
CmpString
MOVE.L RegD0,D0
TST.W D0
BEQ.S @2
MOVE.L RegA0,D0
BSR CheckOddAddress
BMI.S @1
MOVE.L RegD0,D0
SWAP D0
CLR.W D0
SWAP D0
ADD.L RegA0,D0
SUBQ.L #1,D0
BSR CheckOddAddress
BMI retErrStringLength
@2
TST.W RegD0
BEQ retOK
MOVE.L RegA1,D0
BSR CheckOddAddress
BMI.S @1
MOVEQ #0,D0
MOVE.W RegD0,D0
ADD.L RegA1,D0
SUBQ.L #1,D0
BSR CheckOddAddress
BMI retErrStringLength
@1
RTS
UprString
MOVE.L RegD0,D0
TST.W D0
BEQ retOK
MOVE.L RegA0,D0
BSR CheckOddRAM
BMI.S @1
MOVE.L RegD0,D0
SWAP D0
CLR.W D0
SWAP D0
ADD.L RegA0,D0
SUBQ.L #1,D0
BSR CheckOddRAM
BMI retErrStringLength
@1
RTS
StuffHex
BSR String0
BMI.S @1
BSR OddRAM4
@1
RTS
StdTxMeas
TST.W Stack16
BEQ.S @2
BSR OddAddress12
BMI.S @1
MOVEQ #0,D0
MOVE.W Stack16,D0
ADD.L Stack12,D0
BSR CheckOddAddress
BMI retErrLength
@2
BSR RAM8RAM4RAM0
@1
RTS
ScrollRect
BSR Rect8
BMI.S @1
BSR Rgn0
@1
RTS
StdComment
PicComment
TST.W Stack4
BEQ retOK
MOVE.L Stack0,D0
BSR CheckFakeFullHandle
BMI.S @1
MOVEQ #0,D0
MOVE.W Stack4,D0
MOVE.L Stack0,A0
ADD.L (A0),D0
BSR CheckOddAddress
@1
RTS
GetFNum
BSR String4
BMI.S @1
BSR RAM0
@1
RTS
SetString
BSR FullHandle4
BMI.S @1
BSR String0
@1
RTS
AppendMenu
BSR Menu4
BMI.S @1
BSR String0
@1
RTS
ParamText
MOVE.L Stack12,D0
BEQ.S @1
BSR CheckString
BMI.S @2
@1
MOVE.L Stack8,D0
BEQ.S @3
BSR CheckString
BMI.S @2
@3
MOVE.L Stack4,D0
BEQ.S @4
BSR CheckString
BMI.S @2
@4
MOVE.L Stack0,D0
BEQ retOK
BSR CheckString
@2
RTS
SetIText
BSR FullHandle4
BMI.S @1
BSR String0
@1
RTS
GetIText
BSR FullHandle4
BMI.S @1
BSR RAM0
@1
RTS
Munger
MOVE.L Stack20,D0
BSR CheckFullHandle
BMI.S @1
MOVE.L Stack20,A0
_GetHandleSize
TST.L D0
BMI retErrHandle
CMP.L Stack16,D0
BLO retErrOffset
TST.L Stack8
BEQ.S @2
MOVE.L Stack12,D0
BEQ.S @2
BSR CheckOddAddress
BMI.S @1
TST.B Stack8
BNE retErrLength
ADD.L Stack8,D0
BSR CheckOddAddress
BMI retErrLength
@2
MOVE.L Stack4,D0
BEQ retOK
BSR CheckOddAddress
BMI.S @1
TST.B Stack0
BNE retErrLength
ADD.L Stack0,D0
BSR CheckOddAddress
BMI retErrLength
@1
RTS
ErrText Offset,offset
Launch
Chain
BSR AddressA0
BMI.S @1
MOVE.L D0,A0
MOVE.L (A0),D0
BSR CheckString
BMI retErrFileName
@1
RTS
DIPack
MOVE.W Stack0,D0
CMP.W #DILoad,D0
BEQ retOK
CMP.W #DIUnload,D0
BEQ retOK
CMP.W #DIBadMount,D0
BEQ retOK
CMP.W #DIFormat,D0
BEQ retOK
CMP.W #DIVerify,D0
BEQ retOK
CMP.W #DIZero,D0
BEQ String2
BRA.S retErrSelector
ErrText Selector,selector
SFPack
MOVE.W Stack0,D0
CMP.W #SFPutFile,D0
BEQ SFPutFile.
CMP.W #SFPPutFile,D0
BEQ SFPPutFile.
CMP.W #SFGetFile,D0
BEQ SFGetFile.
CMP.W #SFPGetFile,D0
BEQ SFPGetFile.
BRA.S retErrSelector
SFPutFile.
BSR String14
BMI.S @1
BSR String10
BMI.S @1
MOVE.L Stack6,D0
BEQ.S @2
BSR CheckAddress
BMI.S @1
@2
BSR RAM2
@1
RTS
SFPPutFile.
BSR String20
BMI.S @1
BSR String16
BMI.S @1
MOVE.L Stack12,D0
BEQ.S @2
BSR CheckAddress
BMI.S @1
@2
BSR RAM8
BMI.S @1
MOVE.L Stack2,D0
BEQ retOK
BSR CheckAddress
@1
RTS
SFGetFile.
BSR String20
BMI.S @1
MOVE.L Stack16,D0
BEQ.S @2
BSR CheckAddress
BMI.S @1
@2
MOVE.W Stack12,D0
BEQ.S @3
CMP.W #-1,D0
BEQ.S @3
BSR Address10
BMI.S @1
@3
MOVE.L Stack6,D0
BEQ.S @4
BSR CheckAddress
BMI.S @1
@4
BSR RAM2
@1
RTS
SFPGetFile.
BSR String26
BMI.S @1
MOVE.L Stack22,D0
BEQ.S @2
BSR CheckAddress
BMI.S @1
@2
MOVE.W Stack18,D0
BEQ.S @3
CMP.W #-1,D0
BEQ.S @3
BSR Address16
BMI.S @1
@3
MOVE.L Stack12,D0
BEQ.S @4
BSR CheckAddress
BMI.S @1
@4
BSR RAM8
BMI.S @1
MOVE.L Stack2,D0
BEQ retOK
BSR CheckAddress
@1
RTS
SANEPack
MOVE.W Stack0,D0
AND.W #$7FF,D0
CMP.W #$1D,D0
BHS retErrSelector
BRA retOK
ElemsPack
MOVE.W Stack0,D0
LEA ElemsTable,A0
@1
CMP.W #$FFFF,(A0)
BEQ retErrSelector
CMP.W (A0)+,D0
BEQ retOK
BRA.S @1
ElemsTable
DC.W $0000,$0002,$0004,$0006,$0008,$000A,$000C,$000E
DC.W $8010,$8012,$C014,$C016,$0018,$001A,$001C,$001E
DC.W $0020,$FFFF
IUPack
MOVE.W Stack0,D0
CMP.W #IUDateString,D0
BEQ RAM2
CMP.W #IUDatePString,D0
BEQ IUDatePString.
CMP.W #IUTimeString,D0
BEQ RAM2
CMP.W #IUTimePString,D0
BEQ IUTimePString.
CMP.W #IUMetric,D0
BEQ retOK
CMP.W #IUGetIntl,D0
BEQ retOK
CMP.W #IUSetIntl,D0
BEQ FullHandle2
CMP.W #IUMagString,D0
BEQ IUMagString.
CMP.W #IUMagIDString,D0
BEQ IUMagIDString.
BRA retErrSelector
IUDatePString.
IUTimePString.
BSR RAM6
BMI.S @1
BSR FullHandle0
@1
RTS
IUMagString.
IUMagIDString.
TST.W Stack4
BEQ.S @2
MOVE.L Stack10,D0
BSR CheckOddAddress
BMI.S @1
MOVEQ #0,D0
MOVE.W Stack4,D0
ADD.L Stack10,D0
SUBQ.L #1,D0
BSR CheckOddAddress
BMI retErrStringLength
@2
TST.W Stack2
BEQ retOK
MOVE.L Stack6,D0
BSR CheckOddAddress
BMI.S @1
MOVEQ #0,D0
MOVE.W Stack2,D0
ADD.L Stack6,D0
SUBQ.L #1,D0
BSR CheckOddAddress
BMI retErrStringLength
@1
RTS
BDPack
MOVE.W Stack0,D0
CMP.W #NumToString,D0
BEQ OddRAMA0
CMP.W #StringToNum,D0
BEQ StringA0
BRA retErrSelector
;+--------------------------------------------------------------------+
;| These are the dispatch tables: 0 means no discipline for that trap |
;+--------------------------------------------------------------------+
OSTraps
DC.W Open-OSTraps ; 0 Open
DC.W PB-OSTraps ; 1 Close
DC.W Read-OSTraps ; 2 Read
DC.W Write-OSTraps ; 3 Write
DC.W PB-OSTraps ; 4 Control
DC.W PB-OSTraps ; 5 Status
DC.W PB-OSTraps ; 6 KillIO
DC.W GetVolInfo-OSTraps ; 7 GetVolInfo
DC.W Create-OSTraps ; 8 Create
DC.W Delete-OSTraps ; 9 Delete
DC.W OpenRF-OSTraps ; A OpenRF
DC.W Rename-OSTraps ; B Rename
DC.W GetFileInfo-OSTraps ; C GetFileInfo
DC.W SetFileInfo-OSTraps ; D SetFileInfo
DC.W UnmountVol-OSTraps ; E UnmountVol
DC.W PB-OSTraps ; F MountVol
DC.W PB-OSTraps ; 10 Allocate
DC.W PB-OSTraps ; 11 GetEOF
DC.W PB-OSTraps ; 12 SetEOF
DC.W FlushVol-OSTraps ; 13 FlushVol
DC.W GetVol-OSTraps ; 14 GetVol
DC.W SetVol-OSTraps ; 15 SetVol
DC.W 0 ; 16
DC.W Eject-OSTraps ; 17 Eject
DC.W PB-OSTraps ; 18 GetFPos
DC.W InitZone-OSTraps ; 19 InitZone
DC.W 0 ; 1A
DC.W ZoneA0-OSTraps ; 1B SetZone
DCB.W $1F-$1C,0 ; 1C-1E
DC.W PtrA0-OSTraps ; 1F DisposPtr
DC.W PtrA0-OSTraps ; 20 SetPtrSize
DC.W PtrA0-OSTraps ; 21 GetPtrSize
DC.W 0 ; 22
DC.W HandleA0-OSTraps ; 23 DisposHandle
DC.W HandleA0-OSTraps ; 24 SetHandleSize
DC.W HandleA0-OSTraps ; 25 GetHandleSize
DC.W HandleA0-OSTraps ; 26 HandleZone
DC.W HandleA0-OSTraps ; 27 ReallocHandle
DC.W RecoverHandle-OSTraps ; 28 RecoverHandle
DC.W HandleA0-OSTraps ; 29 HLock
DC.W HandleA0-OSTraps ; 2A HUnlock
DC.W HandleA0-OSTraps ; 2B EmptyHandle
DC.W 0 ; 2C
DC.W SetApplLimit-OSTraps ; 2D SetApplLimit
DC.W BlockMove.-OSTraps ; 2E BlockMove
DC.W 0 ; 2F
DC.W RAMA0-OSTraps ; 30 OSEventAvail
DC.W RAMA0-OSTraps ; 31 GetOSEvent
DC.W 0 ; 32
DC.W VInstall.-OSTraps ; 33 VInstall
DC.W VRemove-OSTraps ; 34 VRemove
DC.W OffLine-OSTraps ; 35 OffLine
DC.W 0 ; 36
DC.W 0 ; 37
DC.W WriteParam-OSTraps ; 38 WriteParam
DC.W RAMA0-OSTraps ; 39 ReadDateTime
DC.W 0 ; 3A
DC.W 0 ; 3B
DC.W CmpString-OSTraps ; 3C CmpString
DCB.W $41-$3D,0 ; 3D-40
DC.W SetFilLock-OSTraps ; 41 SetFilLock
DC.W RstFilLock-OSTraps ; 42 RstFilLock
DC.W SetFilType-OSTraps ; 43 SetFilType
DC.W PB-OSTraps ; 44 SetFPos
DC.W PB-OSTraps ; 45 FlushFile
DC.W 0 ; 46
DC.W SetTrapAddress-OSTraps ; 47 SetTrapAddress
DC.W PtrA0-OSTraps ; 48 PtrZone
DC.W HandleA0-OSTraps ; 49 HPurge
DC.W HandleA0-OSTraps ; 4A HNoPurge
DC.W ProcA0-OSTraps ; 4B SetGrowZone
DCB.W $54-$4C,0 ; 4C-53
DC.W UprString-OSTraps ; 54 UprString
DC.W 0 ; 55
DC.W 0 ; 56
DC.W RAMA0-OSTraps ; 57 SetApplBase
DCB.W $100-$58,0 ; 58-FF
ToolTraps
DCB.W $51-$0,0 ; 0-50
DC.W Cursor0-ToolTraps ; 51 SetCursor
DCB.W $55-$52,0 ; 52-54
DC.W Rect4-ToolTraps ; 55 ShieldCursor
DCB.W $5D-$56,0 ; 56-5C
DC.W OddAddress4-ToolTraps ; 5D BitTst
DC.W OddRAM4-ToolTraps ; 5E BitSet
DC.W OddRAM4-ToolTraps ; 5F BitClr
DCB.W $66-$60,0 ; 60-65
DC.W StuffHex-ToolTraps ; 66 StuffHex
DCB.W $6D-$67,0 ; 67-6C
DC.W RAM0-ToolTraps ; 6D InitPort
DC.W RAM0-ToolTraps ; 6E InitGraf
DC.W RAM0-ToolTraps ; 6F OpenPort
DC.W RAM0-ToolTraps ; 70 LocalToGlobal
DC.W RAM0-ToolTraps ; 71 GlobalToLocal
DC.W 0 ; 72
DC.W 0 ; 73
DC.W RAM0-ToolTraps ; 74 GetPort
DC.W BitMap0-ToolTraps ; 75 SetPortBits
DCB.W $79-$76,0 ; 76-78
DC.W Rgn0-ToolTraps ; 79 SetClip
DC.W Rgn0-ToolTraps ; 7A GetClip
DC.W Address0-ToolTraps ; 7B ClipRect
DC.W RAM0-ToolTraps ; 7C BackPat
DC.W Port0-ToolTraps ; 7D ClosePort
DC.W RAM0-ToolTraps ; 7E AddPt
DC.W RAM0-ToolTraps ; 7F SubPt
DC.W RAM4-ToolTraps ; 80 SetPt
DC.W 0 ; 81
DC.W OddAddress8-ToolTraps ; 82 StdText
DC.W 0 ; 83
DC.W String0-ToolTraps ; 84 DrawString
DC.W OddAddress4-ToolTraps ; 85 DrawText
DC.W OddAddress4-ToolTraps ; 86 TextWidth
DCB.W $8B-$87,0 ; 87-8A
DC.W RAM0-ToolTraps ; 8B GetFontInfo
DC.W String0-ToolTraps ; 8C StringWidth
DCB.W $98-$8D,0 ; 8D-97
DC.W RAM0-ToolTraps ; 98 GetPenState
DC.W RAM0-ToolTraps ; 99 SetPenState
DC.W RAM0-ToolTraps ; 9A GetPen
DCB.W $A0-$9B,0 ; 9B-9F
DC.W Rect0-ToolTraps ; A0 StdRect
DC.W Rect0-ToolTraps ; A1 FrameRect
DC.W Rect0-ToolTraps ; A2 PaintRect
DC.W Rect0-ToolTraps ; A3 EraseRect
DC.W Rect0-ToolTraps ; A4 InvertRect
DC.W FillRect-ToolTraps ; A5 FillRect
DC.W EqualRect-ToolTraps ; A6 EqualRect
DC.W RAM8-ToolTraps ; A7 SetRect
DC.W Address4-ToolTraps ; A8 OffsetRect
DC.W Address4-ToolTraps ; A9 InsetRect
DC.W SectRect-ToolTraps ; AA SectRect
DC.W UnionRect-ToolTraps ; AB UnionRect
DC.W RAM0-ToolTraps ; AC Pt2Rect
DC.W Address0-ToolTraps ; AD PtInRect
DC.W Address0-ToolTraps ; AE EmptyRect
DC.W Rect4-ToolTraps ; AF StdRRect
DC.W Rect4-ToolTraps ; B0 FrameRoundRect
DC.W Rect4-ToolTraps ; B1 PaintRoundRect
DC.W Rect4-ToolTraps ; B2 EraseRoundRect
DC.W Rect4-ToolTraps ; B3 InvertRoundRect
DC.W FillRoundRect-ToolTraps ; B4 FillRoundRect
DC.W 0 ; B5
DC.W Rect0-ToolTraps ; B6 StdOval
DC.W Rect0-ToolTraps ; B7 FrameOval
DC.W Rect0-ToolTraps ; B8 PaintOval
DC.W Rect0-ToolTraps ; B9 EraseOval
DC.W Rect0-ToolTraps ; BA InvertOval
DC.W FillOval-ToolTraps ; BB FillOval
DC.W 0 ; BC
DC.W Rect4-ToolTraps ; BD StdArc
DC.W Rect4-ToolTraps ; BE FrameArc
DC.W Rect4-ToolTraps ; BF PaintArc
DC.W Rect4-ToolTraps ; C0 EraseArc
DC.W Rect4-ToolTraps ; C1 InvertArc
DC.W FillArc-ToolTraps ; C2 FillArc
DC.W PtToAngle-ToolTraps ; C3 PtToAngle
DC.W 0 ; C4
DC.W Poly0-ToolTraps ; C5 StdPoly
DC.W Poly0-ToolTraps ; C6 FramePoly
DC.W Poly0-ToolTraps ; C7 PaintPoly
DC.W Poly0-ToolTraps ; C8 ErasePoly
DC.W Poly0-ToolTraps ; C9 InvertPoly
DC.W FillPoly-ToolTraps ; CA FillPoly
DC.W 0 ; CB
DC.W 0 ; CC
DC.W Poly0-ToolTraps ; CD KillPoly
DC.W Poly4-ToolTraps ; CE OffsetPoly
DC.W 0 ; CF
DC.W 0 ; D0
DC.W Rgn0-ToolTraps ; D1 StdRgn
DC.W Rgn0-ToolTraps ; D2 FrameRgn
DC.W Rgn0-ToolTraps ; D3 PaintRgn
DC.W Rgn0-ToolTraps ; D4 EraseRgn
DC.W Rgn0-ToolTraps ; D5 InvertRgn
DC.W FillRgn-ToolTraps ; D6 FillRgn
DC.W 0 ; D7
DC.W 0 ; D8
DC.W Rgn0-ToolTraps ; D9 DisposeRgn
DC.W 0 ; DA
DC.W Rgn0-ToolTraps ; DB CloseRgn
DC.W CopyRgn-ToolTraps ; DC CopyRgn
DC.W Rgn0-ToolTraps ; DD SetEmptyRgn
DC.W Rgn8-ToolTraps ; DE SetRectRgn
DC.W RectRgn-ToolTraps ; DF RectRgn
DC.W Rgn4-ToolTraps ; E0 OffsetRgn
DC.W Rgn4-ToolTraps ; E1 InsetRgn
DC.W Rgn0-ToolTraps ; E2 EmptyRgn
DC.W EqualRgn-ToolTraps ; E3 EqualRgn
DC.W SectRgn-ToolTraps ; E4 SectRgn
DC.W UnionRgn-ToolTraps ; E5 UnionRgn
DC.W DiffRgn-ToolTraps ; E6 DiffRgn
DC.W XorRgn-ToolTraps ; E7 XorRgn
DC.W Rgn0-ToolTraps ; E8 PtInRgn
DC.W RectInRgn-ToolTraps ; E9 RectInRgn
DC.W RAM0-ToolTraps ; EA SetStdProcs
DC.W StdBits-ToolTraps ; EB StdBits
DC.W CopyBits-ToolTraps ; EC CopyBits
DC.W StdTxMeas-ToolTraps ; ED StdTxMeas
DC.W OddRAM4-ToolTraps ; EE StdGetPic
DC.W ScrollRect-ToolTraps ; EF ScrollRect
DC.W OddAddress4-ToolTraps ; F0 StdPutPic
DC.W StdComment-ToolTraps ; F1 StdComment
DC.W PicComment-ToolTraps ; F2 PicComment
DC.W Rect0-ToolTraps ; F3 OpenPicture
DC.W 0 ; F4
DC.W Pict0-ToolTraps ; F5 KillPicture
DC.W DrawPicture-ToolTraps ; F6 DrawPicture
DC.W 0 ; F7
DC.W ScalePt-ToolTraps ; F8 ScalePt
DC.W MapPt-ToolTraps ; F9 MapPt
DC.W MapRect-ToolTraps ; FA MapRect
DC.W MapRgn-ToolTraps ; FB MapRgn
DC.W MapPoly-ToolTraps ; FC MapPoly
DC.W 0 ; FD
DC.W 0 ; FE
DC.W RAM0-ToolTraps ; FF GetFontName
DC.W GetFNum-ToolTraps ; 100 GetFNum
DC.W RAM0-ToolTraps ; 101 SwapFont
DC.W 0 ; 102
DC.W 0 ; 103
DC.W Window0-ToolTraps ; 104 DrawGrowIcon
DC.W DragGrayRgn-ToolTraps ; 105 DragGrayRgn
DC.W String0-ToolTraps ; 106 NewString
DC.W SetString-ToolTraps ; 107 SetString
DC.W Window2-ToolTraps ; 108 ShowHide
DC.W CalcVis-ToolTraps ; 109 CalcVis
DC.W CalcVisBehind-ToolTraps ; 10A CalcVisBehind
DC.W ClipAbove-ToolTraps ; 10B ClipAbove
DC.W PaintOne-ToolTraps ; 10C PaintOne
DC.W PaintBehind-ToolTraps ; 10D PaintBehind
DC.W Window0-ToolTraps ; 10E SaveOld
DC.W Window2-ToolTraps ; 10F DrawNew
DC.W RAM0-ToolTraps ; 110 GetWMgrPort
DC.W RAM0-ToolTraps ; 111 CheckUpdate
DC.W 0 ; 112
DC.W NewWindow-ToolTraps ; 113 NewWindow
DC.W DisposeWindow-ToolTraps ; 114 DisposeWindow
DC.W Window0-ToolTraps ; 115 ShowWindow
DC.W Window0-ToolTraps ; 116 HideWindow
DC.W Window0-ToolTraps ; 117 GetWRefCon
DC.W Window4-ToolTraps ; 118 SetWRefCon
DC.W GetWTitle-ToolTraps ; 119 GetWTitle
DC.W SetWTitle-ToolTraps ; 11A SetWTitle
DC.W Window6-ToolTraps ; 11B MoveWindow
DC.W Window2-ToolTraps ; 11C HiliteWindow
DC.W Window6-ToolTraps ; 11D SizeWindow
DC.W Window4-ToolTraps ; 11E TrackGoAway
DC.W Window0-ToolTraps ; 11F SelectWindow
DC.W Window0-ToolTraps ; 120 BringToFront
DC.W SendBehind-ToolTraps ; 121 SendBehind
DC.W BeginUpdate-ToolTraps ; 122 BeginUpdate
DC.W EndUpdate-ToolTraps ; 123 EndUpdate
DC.W 0 ; 124
DC.W DragWindow-ToolTraps ; 125 DragWindow
DC.W DragTheRgn-ToolTraps ; 126 DragTheRgn
DC.W Rgn0-ToolTraps ; 127 InvalRgn
DC.W Address0-ToolTraps ; 128 InvalRect
DC.W Rgn0-ToolTraps ; 129 ValidRgn
DC.W Address0-ToolTraps ; 12A ValidRect
DC.W GrowWindow-ToolTraps ; 12B GrowWindow
DC.W RAM0-ToolTraps ; 12C FindWindow
DC.W Window0-ToolTraps ; 12D CloseWindow
DC.W Window4-ToolTraps ; 12E SetWindowPic
DC.W Window0-ToolTraps ; 12F GetWindowPic
DC.W 0 ; 130
DC.W String0-ToolTraps ; 131 NewMenu
DC.W Menu0-ToolTraps ; 132 DisposeMenu
DC.W AppendMenu-ToolTraps ; 133 AppendMenu
DC.W 0 ; 134
DC.W Menu2-ToolTraps ; 135 InsertMenu
DCB.W $139-$136,0 ; 136-138
DC.W Menu2-ToolTraps ; 139 EnableItem
DC.W Menu2-ToolTraps ; 13A DisableItem
DC.W 0 ; 13B
DC.W FullHandle0-ToolTraps ; 13C SetMenuBar
DC.W 0 ; 13D
DC.W 0 ; 13E
DC.W GetItemIcon-ToolTraps ; 13F GetItemIcon
DC.W Menu4-ToolTraps ; 140 SetItemIcon
DC.W GetItemStyle-ToolTraps ; 141 GetItemStyle
DC.W Menu4-ToolTraps ; 142 SetItemStyle
DC.W GetItemMark-ToolTraps ; 143 GetItemMark
DC.W Menu4-ToolTraps ; 144 SetItemMark
DC.W Menu4-ToolTraps ; 145 CheckItem
DC.W GetItem-ToolTraps ; 146 GetItem
DC.W SetItem-ToolTraps ; 147 SetItem
DC.W Menu0-ToolTraps ; 148 CalcMenuSize
DC.W 0 ; 149
DC.W 0 ; 14A
DC.W PlotIcon-ToolTraps ; 14B PlotIcon
DC.W 0 ; 14C
DC.W Menu4-ToolTraps ; 14D AddResMenu
DC.W Rect4-ToolTraps ; 14E PinRect
DC.W 0 ; 14F
DC.W Menu0-ToolTraps ; 150 CountMItems
DC.W Menu6-ToolTraps ; 151 InsertResMenu
DC.W 0 ; 152
DC.W 0 ; 153
DC.W NewControl-ToolTraps ; 154 NewControl
DC.W Control0-ToolTraps ; 155 DisposeControl
DC.W Window0-ToolTraps ; 156 KillControls
DC.W Control0-ToolTraps ; 157 ShowControl
DC.W FullHandle0-ToolTraps ; 158 HideControl
DC.W Control4-ToolTraps ; 159 MoveControl
DC.W Control0-ToolTraps ; 15A GetCRefCon
DC.W Control4-ToolTraps ; 15B SetCRefCon
DC.W Control4-ToolTraps ; 15C SizeControl
DC.W Control2-ToolTraps ; 15D HiliteControl
DC.W GetCTitle-ToolTraps ; 15E GetCTitle
DC.W SetCTitle-ToolTraps ; 15F SetCTitle
DC.W Control0-ToolTraps ; 160 GetCtlValue
DC.W Control0-ToolTraps ; 161 GetCtlMin
DC.W Control0-ToolTraps ; 162 GetCtlMax
DC.W Control2-ToolTraps ; 163 SetCtlValue
DC.W Control2-ToolTraps ; 164 SetCtlMin
DC.W Control2-ToolTraps ; 165 SetCtlMax
DC.W Control4-ToolTraps ; 166 TestControl
DC.W DragControl-ToolTraps ; 167 DragControl
DC.W Control8-ToolTraps ; 168 TrackControl
DC.W Window0-ToolTraps ; 169 DrawControls
DC.W Control0-ToolTraps ; 16A GetCtlAction
DC.W Control4-ToolTraps ; 16B SetCtlAction
DC.W FindControl-ToolTraps ; 16C FindControl
DC.W 0 ; 16D
DC.W Dequeue-ToolTraps ; 16E Dequeue
DC.W Enqueue-ToolTraps ; 16F Enqueue
DC.W RAM0-ToolTraps ; 170 GetNextEvent
DC.W RAM0-ToolTraps ; 171 EventAvail
DC.W RAM0-ToolTraps ; 172 GetMouse
DCB.W $176-$173,0 ; 173-175
DC.W RAM0-ToolTraps ; 176 GetKeys
DCB.W $17B-$177,0 ; 177-17A
DC.W Proc0-ToolTraps ; 17B InitDialogs
DC.W GetNewDialog-ToolTraps ; 17C GetNewDialog
DC.W NewDialog-ToolTraps ; 17D NewDialog
DC.W Dialog6-ToolTraps ; 17E SelIText
DC.W Address0-ToolTraps ; 17F IsDialogEvent
DC.W DialogSelect-ToolTraps ; 180 DialogSelect
DC.W Dialog0-ToolTraps ; 181 DrawDialog
DC.W Dialog0-ToolTraps ; 182 CloseDialog
DC.W DisposDialog-ToolTraps ; 183 DisposDialog
DC.W 0 ; 184
DC.W Proc0-ToolTraps ; 185 Alert
DC.W Proc0-ToolTraps ; 186 StopAlert
DC.W Proc0-ToolTraps ; 187 NoteAlert
DC.W Proc0-ToolTraps ; 188 CautionAlert
DC.W 0 ; 189
DC.W 0 ; 18A
DC.W ParamText-ToolTraps ; 18B ParamText
DC.W Proc0-ToolTraps ; 18C ErrorSound
DC.W GetDItem-ToolTraps ; 18D GetDItem
DC.W SetDItem-ToolTraps ; 18E SetDItem
DC.W SetIText-ToolTraps ; 18F SetIText
DC.W GetIText-ToolTraps ; 190 GetIText
DC.W ModalDialog-ToolTraps ; 191 ModalDialog
DCB.W $19F-$192,0 ; 192-19E
DC.W RAM2-ToolTraps ; 19F GetIndType
DCB.W $1A8-$1A0,0 ; 1A0-1A7
DC.W GetResInfo-ToolTraps ; 1A8 GetResInfo
DC.W String0-ToolTraps ; 1A9 SetResInfo
DC.W 0 ; 1AA
DC.W String0-ToolTraps ; 1AB AddResorce
DCB.W $1B3-$1AC,0 ; 1AC-1B2
DC.W SystemClick-ToolTraps ; 1B3 SystemClick
DCB.W $1BD-$1B4,0 ; 1B4-1BC
DC.W GetNewWindow-ToolTraps ; 1BD GetNewWindow
DC.W Window0-ToolTraps ; 1BE GetNewControl
DCB.W $1C6-$1BF,0 ; 1BF-1C5
DC.W RAMA0-ToolTraps ; 1C6 Secs2Date
DC.W RAMA0-ToolTraps ; 1C7 Date2Secs
DCB.W $1CB-$1C8,0 ; 1C8-1CA
DC.W TERec0-ToolTraps ; 1CB TEGetText
DC.W 0 ; 1CC
DC.W TERec0-ToolTraps ; 1CD TEDispose
DC.W Rect2-ToolTraps ; 1CE TextBox
DC.W TERec0-ToolTraps ; 1CF TESetText
DC.W TERec0-ToolTraps ; 1D0 TECalText
DC.W TERec0-ToolTraps ; 1D1 TESetSelect
DC.W TENew-ToolTraps ; 1D2 TENew
DC.W TEUpdate-ToolTraps ; 1D3 TEUpdate
DC.W TERec0-ToolTraps ; 1D4 TEClick
DC.W TERec0-ToolTraps ; 1D5 TECopy
DC.W TERec0-ToolTraps ; 1D6 TECut
DC.W TERec0-ToolTraps ; 1D7 TEDelete
DC.W TERec0-ToolTraps ; 1D8 TEActivate
DC.W TERec0-ToolTraps ; 1D9 TEDeactivate
DC.W TERec0-ToolTraps ; 1DA TEIdle
DC.W TERec0-ToolTraps ; 1DB TEPaste
DC.W TERec0-ToolTraps ; 1DC TEKey
DC.W TERec0-ToolTraps ; 1DD TEScroll
DC.W TERec0-ToolTraps ; 1DE TEInsert
DC.W TERec0-ToolTraps ; 1DF TESetJust
DC.W Munger-ToolTraps ; 1E0 Munger
DC.W FullHandleA0-ToolTraps ; 1E1 HandToHand
DC.W PtrToXHand-ToolTraps ; 1E2 PtrToXHand
DC.W PtrToHand-ToolTraps ; 1E3 PtrToHand
DC.W HandAndHand-ToolTraps ; 1E4 HandAndHand
DCB.W $1E9-$1E5,0 ; 1E5-1E8
DC.W DIPack-ToolTraps ; 1E9 Pack2
DC.W SFPack-ToolTraps ; 1EA Pack3
DC.W SANEPack-ToolTraps ; 1EB Pack4
DC.W ElemsPack-ToolTraps ; 1EC Pack5
DC.W IUPack-ToolTraps ; 1ED Pack6
DC.W BDPack-ToolTraps ; 1EE Pack7
DC.W PtrAndHand-ToolTraps ; 1EF PtrAndHand
DC.W JTPC-ToolTraps ; 1F0 LoadSeg
DC.W JT0-ToolTraps ; 1F1 UnloadSeg
DC.W Launch-ToolTraps ; 1F2 Launch
DC.W Chain-ToolTraps ; 1F3 Chain
DC.W 0 ; 1F4
DC.W GetAppParms-ToolTraps ; 1F5 GetAppParms
DCB.W $1FD-$1F6,0 ; 1F6-1FC
DC.W GetScrap-ToolTraps ; 1FD GetScrap
DC.W OddAddress0-ToolTraps ; 1FE PutScrap
DC.W 0 ; 1FF
;#############################
;## ##
;## TMON patching section ##
;## ##
;#############################
;+------------------------------------------------+
;| Find an area to patch in the main code of TMON |
;+------------------------------------------------+
;|
;|ENTRY: FindInTMON
;|
;|IN: D0,D1 8 bytes to find in TMON's code
;|
;|OUT: Z set if found, clear if not found
;| A0' location of bytes in TMON code
;|
;|Destroys A0,A1.
;|
FindInTMON
MOVE.L TMONStart,A0 ;Start at the beginning of TMON.
LEA A,A1 ;End at the beginning of the user area.
@1 ADDQ #2,A0 ;(we can skip the WH at the beginning)
CMP.L A0,A1
BLS.S NotFoundInTMON
CMP.L (A0),D0 ;Found?
BNE.S @1
CMP.L 4(A0),D1 ;Be sure that 8 bytes match.
BNE.S @1
FoundInTMON
RTS
NotFoundInTMON
MOVEQ #1,D0 ;To set the CC's to non-zero
RTS
SavedBytes EQU $C0 ;C0 bytes are saved after ScrnBase.
SavedScreen LONG 0 ;This is the start of the saved screen.
SaveMode DC 0 ;This is the screen saving mode.
MenuTop DC 0 ;This is the row of the top of the TMON menu.
MenuBottom DC 0 ;This is the row of the menu.
SeeThroughPatch
LEA A,A2 ;As usual, we like A2 pointing to the User Area.
MOVEQ #3,D0 ;Three lines above TMON chars.
MULU ScreenRow,D0
MOVE.W D0,MenuTop-A(A2)
MOVE.W #19,D0 ;Twenty rows of the Menu Bar
MULU ScreenRow,D0 ;Calculate the offset of the address of the start.
MOVE.W D0,MenuBottom-A(A2)
MOVE.L TMONStart,A4 ;($FC) is the start of TMON.
MOVE.L 4(A4),A0 ;(4($FC)) is where a lot of info resides.
MOVE.W (A0)+,D0 ;This is the actual user area size (not necessarily = AreaSize).
LEA SavedBytes(A2),A3 ;The saved screen starts after the saved bytes.
ADD.W D0,A3
MOVE.L A3,SavedScreen-A(A2)
MOVE.W (A0)+,D1 ;This is the screen saving mode.
MOVE.W D1,SaveMode-A(A2)
TST.W D1 ;What is the screen mode?
BNE.S NotFullScreen
;Now, we make the patch that allows the screen to be transparent, if screen saving is on full.
;This is the original routine we are patching:
;7607 MOVEQ #7,D3
;20C1 @1 MOVE.L D1,(A0)+
;20C1 MOVE.L D1,(A0)+
;51CB FFF8 DBRA D3,@1
MOVE.L #$760720C1,D0 ;This is the first 4 bytes of the routine.
MOVE.L #$20C151CB,D1 ;These are the next 4.
BSR FindInTMON
BNE.S @1
;The patch routine is:
;4EB9 ???? ???? JSR ScreenPatch
;4E71 NOP
;4E71 NOP
MOVE.W #$4EB9,(A0)+
LEA ScreenPatch,A1 ;Calculate the address for JSR
MOVE.L A1,(A0)+
MOVE.L #$4E714E71,(A0)+
@1
NotFullScreen
RTS
ScreenPatch
MOVE.L A0,A1 ;Let's calcuate an address.
SUB.L ScrnBase,A1 ;Make an offset from the start of the screen.
CMP.W MenuTop,A1 ;Check if it is above the menu.
BLO.S NormalFill
CMP.W MenuBottom,A1 ;Check if it is below the menu.
BHS.S NormalFill
BlackFill MOVEQ #$FFFFFFFF,D1
BRA.S FillLine
WhiteFill MOVEQ #$00000000,D1
NormalFill
CMP.L #$AFFFFFFF,D1 ;$AAAAAAAA>$AFFFFFFF<-$55555555
BMI.S ShowThrough ;Show through if it is A's or 5's
FillLine
MOVEQ #15,D3 ;This is the original fill routine
@1 MOVE.L D1,(A0)+
DBRA D3,@1
RTS
ShowThrough
ADD.L SavedScreen,A1 ;Point to the saved screen.
MOVEQ #15,D3 ;Allow the application to show through.
@1 MOVE.L (A1)+,(A0)+
DBRA D3,@1
RTS
DebuggerPatch
;This patch allows TMON to step through the _Debugger opcode.
;This is the original routine we are patching:
;0240 F9FF AND.W #$F9FF,D0
;0C40 A9FF CMP.W #$A9FF,D0
MOVE.L #$0240F9FF,D0 ;This is the first 4 bytes of the routine.
MOVE.L #$0C40A9FF,D1 ;These are the next 4.
BSR FindInTMON
BNE.S @1
;The patch routine is:
;0240 F9FF AND.W #$F9FF,D0
;0C40 FFFF CMP.W #$FFFF,D0
MOVE.B #$FF,6(A0)
@1
RTS
GetTrapAddressPatch
;This patch allows TMON to work with the original HyperDrive
;20 software (subsequently fixed by GCC) and some other software
;that patches _GetTrapAddress and does not preserve register A2.
;This is the recognition for the original routine:
;2F0A MOVE.L A2,-(A7)
;2602 MOVE.L D2,D3
;7046 MOVEQ #GetTrapAddress,D0
;A146 _GetTrapAddress
MOVE.L #$2F0A2602,D0 ;This is the first 4 bytes of the recognizer routine.
MOVE.L #$7046A146,D1 ;These are the next 4.
BSR FindInTMON
BNE.S @1
;Changes go here: A2 to A3
;0000: 2F0A MOVE.L A2,-(A7)
; 2F0B MOVE.L A3,-(A7)
MOVE.W #$2F0B,$0000(A0)
;0008: 2448 MOVE.L A0,A2
; 2648 MOVE.L A0,A3
MOVE.W #$2648,$0008(A0)
;0018: 4E92 JSR (A2)
;0018: 4E93 JSR (A3)
MOVE.W #$4E93,$0018(A0)
;002A: 245F MOVE.L (A7)+,A2
;002A: 265F MOVE.L (A7)+,A3
MOVE.W #$265F,$002A(A0)
@1
RTS
;#############################
;## ##
;## Cursor fixing section ##
;## ##
;#############################
FirstSaved EQU ScrnBase
LastSaved EQU FirstSaved+SavedBytes
SavedBase EQU ScrnBase-LastSaved(A3)
SavedTemp EQU MTemp-LastSaved(A3)
SavedRaw EQU RawMouse-LastSaved(A3)
SavedMouse EQU Mouse-LastSaved(A3)
SavedPin EQU CrsrPin-LastSaved(A3)
CrsrPin. EQU CrsrPin+4
SavedPin. EQU CrsrPin.-LastSaved(A3)
SavedRect EQU CrsrRect-LastSaved(A3)
SavedCursor EQU TheCrsr-LastSaved(A3)
SavedAddr EQU CrsrAddr-LastSaved(A3)
SavedSave EQU CrsrSave-LastSaved(A3)
SavedVis EQU CrsrVis-LastSaved(A3)
SavedBusy EQU CrsrBusy-LastSaved(A3)
SavedNew EQU CrsrNew-LastSaved(A3)
SavedCouple EQU CrsrCouple-LastSaved(A3)
SavedState EQU CrsrState-LastSaved(A3)
SavedObscure EQU CrsrObscure-LastSaved(A3)
SavedScale EQU CrsrScale-LastSaved(A3)
SavedMask EQU MouseMask-LastSaved(A3)
SavedOffset EQU MouseOffset-LastSaved(A3)
;
;This fixes up the way the cursor works in TMON.
;
CursorEnter
LEA A,A2 ;Point to A as usual.
MOVE.L SavedScreen,A3 ;Point A3 to the saved cursor globals.
TST.W SaveMode-A(A2) ;Check out save mode.
BNE.S @1
TST.B SavedBusy ;If a cursor routine is executing,
BNE.S @1 ;don't play with the cursor.
TST.B SavedVis ;If the cursor was not visible,
BEQ.S @1 ;don't play with it.
TST.B SavedCouple ;If the cursor is not coupled,
BEQ.S @1 ;don't play with it.
MOVE.B #1,CrsrBusy ;Mark the cursor busy.
LEA SavedRect,A0 ;Restore the old cursor rectangle.
LEA CrsrRect,A1
MOVE.L (A0)+,(A1)+
MOVE.L (A0),(A1)
MOVE.L SavedAddr,D1 ;Get the old cursor address.
MOVE.L D1,D0
SUB.L ScrnBase,D0
ADD.L SavedScreen,D0
MOVE.L D0,CrsrAddr ;Modify it to point to the buffer.
LEA SavedSave,A0 ;Get the saved bytes.
LEA CrsrSave,A1 ;Into the real bytes.
MOVE.L #4*16,D0
_BlockMove
SUB.W #1,SavedState ;Subtract 1 to indicated Hiding.
PEA @1
MOVE.L JShowCursor,-(SP)
MOVE.L JHideCursor,-(SP)
RTS
@1
ST CrsrCouple ;Now, make sure the cursor can be used.
MOVEQ #-1,D0
MOVE.L D0,MouseMask
CLR.L MouseOffset
RTS ;Continue with the Record routine.
CursorExit
LEA A,A2 ;Point to A as usual.
MOVE.L SavedScreen,A3 ;Point A3 to the saved cursor globals.
TST.W SaveMode-A(A2) ;Check out save mode.
BNE @1
TST.B SavedBusy ;If a cursor routine is executing,
BNE @1 ;don't play with the cursor.
TST.B SavedCouple ;If the mouse is not coupled to the cursor,
BEQ @1 ;don't move it.
MOVE.B #1,CrsrBusy ;Mark the cursor busy.
CLR.B CrsrVis ;Fix up some variables.
MOVE.W SavedState,CrsrState
MOVE.L SavedMask,MouseMask
MOVE.L SavedOffset,MouseOffset
LEA SavedPin,A0 ;Get the pin rectangle and the cursor.
LEA CrsrPin,A1
MOVE.L #2*8+2*(2*16)+4,D0
_BlockMove
MOVE.L RawMouse,D0 ;Get the current mouse address.
BSR.S DoPinStuff
MOVE.L D0,RawMouse ;Save it as Raw and Temp.
MOVE.L D0,MTemp
AND.L MouseMask,D0 ;Mask it.
MOVE.L MouseOffset,D1 ;Offset it?
BEQ.S @3
ADD.L D1,D0 ;yes.
BSR.S DoPinStuff
@3 MOVE.L D0,Mouse
CLR.B CrsrNew
CLR.B CrsrObscure
TST.B SavedObscure ;If it was obscured,
BEQ.S @4
SNE SavedVis ;pretend it was visible.
@4
TST.B SavedVis ;Was it visible when we entered?
BEQ.S @5
MOVE.L SavedScreen,ScrnBase ;Fake out the screen.
CLR.W CrsrState ;(just to make sure)
PEA @2
MOVE.L JShowCursor,-(SP)
RTS
@2
MOVE.B #1,CrsrBusy
MOVE.L CrsrAddr,D0 ;Get the address of saved data.
SUB.L ScrnBase,D0 ;Subtract the value of the screen.
ADD.L SavedBase,D0 ;Add the value of the real screen.
MOVE.L D0,CrsrAddr ;Set that address.
@5
LEA MTemp,A0 ;Restore the variables.
LEA SavedTemp,A1 ;Store over the saved variables.
MOVE.L #SavedBytes-4,D0 ;Restore all but the ScrnBase.
_BlockMove
CLR.B SavedBusy
CLR.B CrsrBusy
@1
RTS
DoPinStuff
CMP.W left(A0),D0 ;This routine is copied out of the ROM
BGE.S @1
MOVE.W left(A0),D0
@1
CMP.W right(A0),D0
BLE.S @2
MOVE.W right(A0),D0
SUBQ.W #1,D0
@2
SWAP D0
CMP.W top(A0),D0
BGE.S @3
MOVE.W top(A0),D0
@3
CMP.W bottom(A0),D0
BLE.S @4
MOVE.W bottom(A0),D0
SUBQ.W #1,D0
@4
SWAP D0
RTS
;#####################
;## ##
;## Odds and Ends ##
;## ##
;#####################
;
;The following makes the _Debugger trap work properly.
;
Debugger EQU $1FF
DebuggerInit
MOVEQ #12,D0
_NewPtr,Sys
MOVE.L A0,A1
MOVE.W #$4EF9,(A0)+ ;JMP ABS.L
LEA DebuggerIntercept,A3
MOVE.L A3,(A0)+
MOVE.L A0,A2
MOVE.W #$4EF9,(A0)+ ;JMP ABS.L
LEA UndefinedIntercept,A3
MOVE.L A3,(A0)+
MOVE.W #Debugger,D0
_GetTrapAddress
MOVE.L A0,A3
MOVE.W #Debugger,D0
MOVE.L A1,A0
_SetTrapAddress
MOVE.W #Debugger-1,D1 ;All traps except _Debugger
FixUndefined
MOVE.W D1,D0
_GetTrapAddress
CMP.L A0,A3 ;Same as Debugger?
BNE.S @1
MOVE.W D1,D0
MOVE.L A2,A0
_SetTrapAddress
@1
DBRA D1,FixUndefined
RTS
DebuggerIntercept
MOVE.W SR,-(SP)
MOVEM.L A0/A1,-(SP)
MOVE.L 10(SP),A0
CMP.L TMONStart,A0
BLO.S @1
LEA EndUserArea,A1
CMP.L A1,A0
BHS.S @1
MOVEM.L (SP)+,A0/A1
MOVE.W (SP)+,SR
RTS
@1
MOVEM.L (SP)+,A0/A1
TRAPMon '_Debugger'
UndefinedIntercept
MOVE.W SR,-(SP)
MOVEM.L A0/A1,-(SP)
MOVE.L 10(SP),A0
CMP.L TMONStart,A0
BLO.S @1
LEA EndUserArea,A1
CMP.L A1,A0
BHS.S @1
MOVEM.L (SP)+,A0/A1
MOVE.W (SP)+,SR
RTS
@1
MOVEM.L (SP)+,A0/A1
TRAPMon 'Undefined A-trap'
;
;The following makes Free Form sound work properly.
;
VInstall EQU $33
FreeFormPatch
MOVE.W #VInstall,D0
_GetTrapAddress
CMP.W #$6D1A,$34(A0) ;If it is the correct BLT.S
BNE.S DontPatchFreeForm
MOVE.B #$60,$34(A0) ;Make it a BRA.S
DontPatchFreeForm
RTS
;
;The following allows the AppleTalk interface code to work properly.
;
AppleTalkPatch
MOVE.B #1,$E0 ;Don't ask.
RTS
;
;The following saves MemTop so it is valid later. It seems Switcher likes
;to mess with it.
;
SaveMemTop
LEA RealMemTop,A0
MOVE.L MemTop,(A0)
RTS
RealMemTop LONG 0
;##################################
;## ##
;## End of User Area (padding) ##
;## ##
;##################################
DCB.B AreaSize+A-*,0 ;Fill out user area to a even multiple of 256
EndUserArea
END